线段树专题-黑白棋盘

题目来源

BZOJ−1453BZOJ-1453BZOJ−1453

题意

  • QQQ次操作
  • 每次操作给出(x,y)(x,y)(x,y),将(x,y)(x,y)(x,y)个格子颜色取反
  • 每次操作后,输出棋盘上黑白联通块的个数
  • n≤100,Q≤104n \le 100,Q \le 10^4n≤100,Q≤104

题解

显然不能直接套并查集,因为直接套并查集的时间复杂度为O(n2Q)=108O(n^2Q) = 10^8O(n2Q)=108

考虑使用线段树维护并查集.

线段树维护的是[l,r][l,r][l,r]行中黑白联通块的数量,其中重点维护l,rl,rl,r两行的并查集.

遇到合并操作的时候,如把[l1,r1][l_1,r_1][l1​,r1​]与[l2,r2][l_2,r_2][l2​,r2​]做合并.

首先将各自的黑白联通块数量合并到[l1,r2][l_1,r_2][l1​,r2​]中去,然后再从中减去并查集合并时候造成的联通块减小的部分数.

首先构建一颗大小为4n4n4n的并查集,把l1l_1l1​并查集放于第一层,r1r1r1并查集放于第二层,把l2l_2l2​并查集放于第三层,r2r2r2并查集放于第四层.注意此时第一层和第二层有关系,第三层和第四层有关系.然后枚举i:[1,n]i : [1,n]i:[1,n],打通第二层和第三层之间的关系,并更新黑白联通块的个数.

因为中间的二三层在做完以上操作的时候已经没有用了,因此我们要把它们删掉,并且将规模4n4n4n的并查集缩小至2n2n2n.

我们需要玩一个小trictrictric,即把第一层的并查集的根节点全都换成第一层里的数,把第四层并查集里的根节点全都换成第二层里的数.这样的话并查集又可以缩小为2n2n2n了.

小tric的代码

rep(i,1,n) {tmp[findset(pa,pa[i])] = i;tmp[findset(pa,pa[i+3*n])] = i+n;
}
rep(i,1,n) {ns[rt].pa[i] = tmp[findset(pa,pa[i])];ns[rt].pa[i+n] = tmp[findset(pa,pa[i+3*n])];
}

代码

#include <cstdio>
#include <iostream>#define rep(x,a,b) for(int x = a;x <= b;++x)
#define pr(x) std::cout << #x << ":" << x << std::endl
const int N = 201;
int n,m;
int bit[N][N];
void initset(int pa[],int n) {rep(i,1,n) pa[i] = i;}
int findset(int pa[],int x) {return x == pa[x]?x:pa[x] = findset(pa,pa[x]);}
int join(int pa[],int x,int y) {int px = findset(pa,x),py = findset(pa,y);if(px != py) {pa[px] = py;return true;}return false;
}
struct Node{int pa[2*N];int color[2];void init(int line) {color[0] = color[1] = 0;initset(pa,n);rep(i,1,n-1) if(bit[line][i] == bit[line][i+1])join(pa,i+1,i);rep(i,1,n) pa[i+n] = pa[i];rep(i,1,n)if(findset(pa,i) == i) color[bit[line][i]] ++;}
}ns[N<<2];
int pa[N<<2],tmp[N<<2];
void maintain(int rt,int l,int r){int mid = (l + r) / 2;int lc = rt << 1,rc = rt << 1 | 1;rep(i,1,2*n) {pa[i] = ns[lc].pa[i];pa[i+2*n] = ns[rc].pa[i] + 2*n;}ns[rt].color[0] = ns[lc].color[0] + ns[rc].color[0];ns[rt].color[1] = ns[lc].color[1] + ns[rc].color[1];rep(i,1,n) {if(bit[mid][i] == bit[mid+1][i]) {if(join(pa,i+2*n,i+n)){ns[rt].color[bit[mid][i]] --;}}}rep(i,1,n) {tmp[findset(pa,pa[i])] = i;tmp[findset(pa,pa[i+3*n])] = i+n;}rep(i,1,n) {ns[rt].pa[i] = tmp[findset(pa,pa[i])];ns[rt].pa[i+n] = tmp[findset(pa,pa[i+3*n])];}
}
void build(int rt,int l,int r) {if(l == r) {ns[rt].init(l);return ;}int mid = (l + r) / 2;build(rt<<1,l,mid);build(rt<<1|1,mid+1,r);maintain(rt,l,r);
}
void change(int rt,int l,int r,int pos) {if(l == r) ns[rt].init(l);else {int mid = (l + r) / 2;if(pos <= mid) change(rt<<1,l,mid,pos);else change(rt<<1|1,mid+1,r,pos);maintain(rt,l,r);}
}
int main() {std::ios::sync_with_stdio(false);std::cin >> n;rep(i,1,n) rep(j,1,n) {std::cin >> bit[i][j];}build(1,1,n);//std::cout << ns[1].color[0] << " " << ns[1].color[1] << std::endl;std::cin >> m;while(m--) {int x,y;std::cin >> x >> y;bit[x][y] ^= 1;change(1,1,n,x);std::cout << ns[1].color[1] << " " << ns[1].color[0] << std::endl;}
}

线段树专题-黑白棋盘 BZOJ-1453相关推荐

  1. 线段树专题-等差子序列 BZOJ-2124

    线段树专题-等差子序列 感谢 感谢孙耀峰的线段树PPT,使我获益匪浅. 题目来源 BZOJ−2124BZOJ-2124BZOJ−2124 题意 给出长度为nnn的1−n1-n1−n的排列AAA 问是否 ...

  2. 2018 UESTC 线段树专题

    A - 一棵简单的线段树 A[1...n]初始全为0. 1. 给两个数p 和 x(1≤p≤n),单点更新 A[p] <- x 2. 给两个数L和R (1≤L<R≤n),  L到R区间里这几 ...

  3. 蒟蒻君的刷题日记Day12(线段树专题T4):P8082 [COCI2011-2012#4] KEKS 线段树版题解

    解题思路 看题解区的大佬们用的都是单调栈,本蒟蒻献上一篇线段树题解. 整个数最大,首先位数是确定的,则肯定优先考虑高位大小. 大体思路就是从前向后依次求出每一位的值(好像是废话). 对于第 iii 位 ...

  4. 线段树专题 A(单点更新)

    #include <iostream> #include<cstdio> #include<cstring> using namespace std; const ...

  5. 【POJ 2482】 Stars in Your Window(线段树+离散化+扫描线)

    [POJ 2482] Stars in Your Window(线段树+离散化+扫描线) Time Limit: 1000MS   Memory Limit: 65536K Total Submiss ...

  6. 【BZOJ3821/UOJ46】玄学(二进制分组,线段树)

    [BZOJ3821/UOJ46]玄学(二进制分组,线段树) 题面 BZOJ UOJ 题解 呜,很好的题目啊QwQ. 离线做法大概可以线段树分治,或者直接点记录左右两次操作时的结果,两个除一下就可以直接 ...

  7. 【BZOJ4991】我也不知道题目名字是什么(线段树)

    [BZOJ4991]我也不知道题目名字是什么(线段树) 题面 BZOJ 题解 对于线段树维护的区间维护以下东西: 区间左(右)端开始(结束)的最长(短)子串的长度 左端右端的值,以及当前区间内的答案 ...

  8. ACM之路(14)—— 线段树的日常(上)

    我的线段树简直有毒,各种错误都能忙上半天.做了kuangbin的线段树专题的一半,还有一半留到以后去做. 链接:http://acm.hust.edu.cn/vjudge/contest/view.a ...

  9. HDU1255 覆盖的面积 (线段树 + 扫描线)

    题目链接:覆盖的面积 大致题意 现在有平面直角坐标系xoy, 有n个平行于x轴y轴的矩形, 给出这些矩形的左上角和右下角的坐标, 让你求出这些矩形组成的图形中被至少两个矩形覆盖的部分的总面积. 解题思 ...

最新文章

  1. 商贸通服装鞋帽版客户端无法连接服务器的问题(自己遇到的,已解决)
  2. 加载BeanFactory
  3. 实例1、查询数据(多级组织)
  4. 如何用手机打开dcm格式图片_手机也能当扫描仪用?如何用手机扫描图片?
  5. 机器学习算法与Python实践之(二)支持向量机(SVM)初
  6. 接口隔离原则_是时候深入学习一下“接口隔离原则”了
  7. Fomo3d常见问题
  8. CodeForces - 208E Blood Cousins(树上倍增+二分/树上启发式合并)
  9. mxGraph实现按住ctrl键盘拖动图形实现复制图形功能
  10. Qt Designer中部件的tabletTracking和mouseTracking属性
  11. 《浪潮之巅》读书笔记3
  12. 一些值得学习的Unity教程 (很实用的包括源码)
  13. 职业-企业家:企业家
  14. idea 调节背景护眼_IDEA 护眼色设置 背景行颜色取消等设置
  15. 无法安装打印机,打印处理器不存在
  16. VSCode搭建STM32开发环境(极简自我搭建懒人直接使用插件)
  17. 创建Substrate 私有网络
  18. JAVA 仿XP画图板的总结
  19. Windows2000、2003浏览器无法上网、无法联网
  20. 行人重识别多个数据集格式统一为market1501格式

热门文章

  1. 东南大学计算机网络_东南大学,2020年东南大学高考录取分数线分析
  2. vue 调用mutation方法_Vuex白话教程第三讲:Vuex旗下的Mutation
  3. python数据抓取课程_Python爬虫入门教程 21-100 网易云课堂课程数据抓取
  4. 计算机网络实验arp协议分析,计算机网络ARP地址协议解析实验报告
  5. leetcode309. 最佳买卖股票时机含冷冻期
  6. Java当中迭代器的使用(遍历容器ArrayList, HashSet,HashMap)
  7. 「offer来了」面试中必考的15个html知识点
  8. TypeScript,从0到入门带你进入类型的世界
  9. 操作系统复习题+最终版
  10. 数据结构与算法--我们来玩丢手绢(约瑟夫环问题)