题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1453

题意:一个 n*n 的矩阵,每个位置有黑/白两种颜色,有 m 次操作,每次可以翻转其中一个位置的格子颜色,问每次操作后黑色和白色连通块的个数。

题解:考虑若没有翻转颜色的操作时,可以用并查集来找出两种连通块的个数,加上修改的操作,可以用线段树维护并查集的信息。对每列建线段树,合并时将边界合并,修改从叶子到根进行合并,详见代码~

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define mst(a,b) memset((a),(b),sizeof(a))
#define mp(a,b) make_pair(a,b)
#define pi acos(-1)
#define pii pair<int,int>
#define pb push_back
const int INF = 0x3f3f3f3f;
const double eps = 1e-;
const int MAXN = 3e5 + ;
const int MAXM = 1e7 + ;
const ll mod = 1e9 + ; int n, m;
int s[][], fa[ * ]; int id(int x,int y) {
return x * n + y;
} int findd(int x) {
return x == fa[x] ? x : fa[x] = findd(fa[x]);
} struct node {
int l[],r[],ans[];
}st[<<]; node mergee(node &a,node &b,int mid) {
node c;
for(int i = ; i <= n; i++) {
c.l[i] = a.l[i], c.r[i] = b.r[i];
fa[a.l[i]] = a.l[i], fa[a.r[i]] = a.r[i];
fa[b.l[i]] = b.l[i], fa[b.r[i]] = b.r[i];
}
for(int i = ; i < ; i++) c.ans[i] = a.ans[i] + b.ans[i];
for(int i = ; i <= n; i++) {
if(s[i][mid] == s[i][mid + ]) {
int x = findd(a.r[i]), y = findd(b.l[i]);
if(x == y) continue;
c.ans[s[i][mid]]--, fa[x] = y;
}
}
for(int i = ; i <= n; i++) {
c.l[i] = findd(c.l[i]);
c.r[i] = findd(c.r[i]);
}
return c;
} void build(int rt,int l,int r) {
if(l == r) {
st[rt].ans[] = st[rt].ans[] = ;
for(int i = ; i <= n; i++) {
st[rt].l[i] = st[rt].r[i] = fa[id(i,l)] = id(i,l);
st[rt].ans[s[i][l]]++;
}
for(int i = ; i <= n; i++) {
if(s[i][l] == s[i - ][l]) {
st[rt].l[i] = st[rt].r[i] = fa[id(i,l)] = fa[id(i - ,l)];
st[rt].ans[s[i][l]]--;
}
}
return ;
}
int mid = (l + r) >> ;
build(rt<<,l,mid);
build(rt<<|,mid + ,r);
st[rt] = mergee(st[rt<<],st[rt<<|],mid);
} void update(int rt,int l,int r,int pos) {
if(l == r) {
st[rt].ans[] = st[rt].ans[] = ;
for(int i = ; i <= n; i++) {
st[rt].l[i] = st[rt].r[i] = fa[id(i,l)] = id(i,l);
st[rt].ans[s[i][l]]++;
}
for(int i = ; i <= n; i++) {
if(s[i][l] == s[i - ][l]) {
st[rt].l[i] = st[rt].r[i] = fa[id(i,l)] = fa[id(i - ,l)];
st[rt].ans[s[i][l]]--;
}
}
return ;
}
int mid = (l + r) >> ;
if(pos <= mid) update(rt<<,l,mid,pos);
else update(rt<<|,mid + ,r,pos);
st[rt] = mergee(st[rt<<],st[rt<<|],mid);
} int main() {
#ifdef local
freopen("data.txt", "r", stdin);
// freopen("data.txt", "w", stdout);
#endif
scanf("%d",&n);
for(int i = ; i <= n; i++)
for(int j = ; j <= n; j++)
scanf("%d",&s[i][j]);
build(,,n);
scanf("%d",&m);
while(m--) {
int x,y;
scanf("%d%d",&x,&y);
s[x][y] ^= ;
update(,,n,y);
printf("%d %d\n",st[].ans[],st[].ans[]);
}
return ;
}

BZOJ 1453 (线段树+并查集)的更多相关文章

  1. BZOJ 3211 线段树+并查集

    思路: 我们很容易发现 一个数开根号 开几(很小)次 就到了1 1 再怎么开 都是1 由于这个性质 我们就可以用并查集 了 //By SiriusRen #include <cmath> ...

  2. [WC2005]双面棋盘(线段树+并查集)

    线段树+并查集维护连通性. 好像 \(700ms\) 的时限把我的常数超级大的做法卡掉了, 必须要开 \(O_2\) 才行. 对于线段树的每一个结点都开左边的并查集,右边的并查集,然后合并. \(Co ...

  3. 2022.02.27 CF811E Vladik and Entertaining Flags(线段树+并查集)

    2022.02.27 CF811E Vladik and Entertaining Flags(线段树+并查集) https://www.luogu.com.cn/problem/CF811E Ste ...

  4. [BZOJ 3123] [SDOI 2013]森林(可持久化线段树+并查集+启发式合并)

    [BZOJ 3123] [SDOI 2013]森林(可持久化线段树+启发式合并) 题面 给出一个n个节点m条边的森林,每个节点都有一个权值.有两种操作: Q x y k查询点x到点y路径上所有的权值中 ...

  5. bzoj 2054: 疯狂的馒头(线段树||并查集)

    链接:https://www.lydsy.com/JudgeOnline/problem.php?id=2054 线段树写法: 点的颜色只取决于最后一次染的颜色,所以我们可以倒着维护,如果当前区间之前 ...

  6. 【BZOJ 4662】 4662: Snow (线段树+并查集)

    4662: Snow Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 136  Solved: 47 Description 2333年的某一天,临冬突 ...

  7. BZOJ 3319 黑白树 并查集+线段树

    这这这这这这什么毒瘤题!!!!!!!!!!!!!!!!!!!!!!!!!!!! 卡LCT(优秀的LCT由于是均摊本身就带着2,3的常数在,而且这道题对于LCT标记十分难维护,又得乘上4,5然后就炸了) ...

  8. BZOJ 2733 [HNOI2012]永无乡 ——线段树 并查集

    用并查集维护联通块. 用线段树的合并来合并联通块. 自己YY了一个写法. #include <map> #include <cmath> #include <queue& ...

  9. poj 2528 Mayor's posters 线段树 || 并查集 离线处理

    题目链接 题意 用不同颜色的线段覆盖数轴,问最终数轴上有多少种颜色? 注:只有最上面的线段能够被看到:即,如果有一条线段被其他的线段给完全覆盖住,则这个颜色是看不到的. 法一:线段树 按题意按顺序模拟 ...

随机推荐

  1. EMR-LDAP配置

    usersync是负责在配置policy的时候可选用户有ldap里的用户,admin是负责登录webui的 https://cwiki.apache.org/confluence/display/RA ...

  2. 【转帖】PostgreSQL之 使用扩展Extension

    PostgreSQL之 使用扩展Extension https://www.cnblogs.com/lnlvinso/p/11042677.html 挺好的文章.自己之前没有系统学习过 扩展.. 目前 ...

  3. Mac查看端口号是否被占用及释放

    1.查看使用端口进程 lsof -i: 端口号 2.释放进程 kill 你的PID 3.再次执行第一步,是否无进程占用 lsof -i: 端口号

  4. Redis 原子操作——事务

    MULTI 标记一个事务块的开始. 事务块内的多条命令会按照先后顺序被放进一个队列当中,最后由 EXEC 命令原子性(atomic)地执行. 可用版本: >= 1.2.0 时间复杂度: O(1) ...

  5. 微信小程序 基本介绍及组件

    创建项目 微信开发工具深入介绍 https://developers.weixin.qq.com/miniprogram/dev/devtools/devtools.html 基本项目目录 1. 配置 ...

  6. Python补充4——替换与修改

    最近在自学Python ,在学习过程中发现一个问题,就是Python 的替换与修改. 按照中文思维,替换与修改有什么区别吗?如果发生了部分替换不就是修改了吗?如果修改了不就是新对象替换了老对象吗? 实 ...

  7. 用shell脚本安装MySQL-5.7.22-Percona版本

    #!/bin/bash MySQL_Package=Percona-Server-5.7.22-22-Linux.x86_64.ssl101.tar.gz Package_Source=Percona ...

  8. 【转】STM32的FSMC详解

    STM32的FSMC真是一个万能的总线控制器,不仅可以控制SRAM,NOR FLASH,NAND FLASH,PC Card,还能控制LCD,TFT. 一般越是复杂的东西,理解起来就很困难,但是使用上 ...

  9. 怎样监听HTTP请求的发出与完成

    1. 监听HTTP请求发出的事件是: xhr.onloadstart 2. 监听HTTP请求结束的事件是: xhr.onloadend xhr.onloadstart = function() { / ...

  10. C# 将一种类型的数组转化为另一种类型的数组

    //字符串数组(源数组) "}; //整型数组(目标数组) int[] iNums; //转换方法 iNums = Array.ConvertAll<string, int>(s ...