题目链接: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. Object类的equals方法 常用API

    boolean equals (Object obj)(return this==obj):  p1.equals(p2): 基本数据类型比较的是值      引用数据类型:默认比较的是两个对象的地址 ...

  2. *#【Python】【基础知识】【模块】【tkinter】【学用tkinter画图/制作窗口】

    Python 提供了多个图形开发界面的库,几个常用 Python GUI 库如下: Tkinter: Tkinter 模块(Tk 接口)是 Python 的标准 Tk GUI 工具包的接口 . Tk ...

  3. Redis提供的持久化机制

    Redis是一种面向“key-value”类型数据的分布式NoSQL数据库系统,具有高性能.持久存储.适应高并发应用场景等优势.它虽然起步较晚,但发展却十分迅速. 近日,Redis的作者在博客中写到, ...

  4. LC 387. First Unique Character in a String

    题目描述 Given a string, find the first non-repeating character in it and return it's index. If it doesn ...

  5. ELinq学习一

    ELinq安装:在Nuget控制台中输入:install-package ELinq一.ELinq与DLinq和EF的功能差异 二.数据库对照表 三.CRUD操作1.插入(Insert)(1)简单形式 ...

  6. 【温故知新】php 魔术方法

    <?php class Magic{ private $name; /** *构造方法,在类被实例化时自动调用,一般用于初始化操作 */ public function __construct( ...

  7. 日志(logging)与正则(re)模块

    logging模块 #日志:日常的流水 =>日志文件,将程序运行过程中的状态或数据进行记录,一般都是记录到日志文件中 #1.logging模块一共分为五个打印级别 debug.info.warn ...

  8. Mac下安装Redis及Redis Desktop Manager

    1.简介 Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库.缓存和消息中间件. 它支持多种类型的数据结构,如 字符串(strings), 散列(hashes), 列表 ...

  9. Java中接口是否可以继承多个接口?

    可以. 接口是常量值和方法定义的集合.接口是一种特殊的抽象类. java类是单继承的.classB Extends classA java接口可以多继承.Interface3 Extends Inte ...

  10. paypal支付 NVP支付 paypal 手续费 GetTransactionDetails

    主要内容: 本文章主要讲解的是NVP的对接,以最简单的接口案例,讲解一下对接NVP的方案. 先提供下paypal 官方文档的主要功能对接说明,如下 1.请求API 服务器端点 描述 https://a ...