题目链接: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. cook,session

    //发送session request.getSession().setAttribute("user", "zs1"); //发送cookie //需要自动登 ...

  2. Spark学习一:Spark概述

    1.1 什么是Spark ​ Apache Spark 是专为大规模数据处理而设计的快速通用的计算引擎. ​ 一站式管理大数据的所有场景(批处理,流处理,sql) ​ spark不涉及到数据的存储,只 ...

  3. FastJson 介绍

    Json详解 Json是一种轻量级的数据交换格式,采用一种“键:值”对的文本格式来存储和表示数据,在系统交换数据过程中常常被使用,是一种理想的数据交换语言.在使用 Java 做 Web 开发时,不可避 ...

  4. DB2部分查询SQL

    /* 部分SQL */ --添加主键 alter TABLE TABLE_SCHEMA.TABLE_NAME add constraint PK_TABLE_NAME primary key(COL1 ...

  5. S02_CH10_ User GPIO实验

    S02_CH10_ User GPIO实验 在之前的第四章课程中,我们详细的讲解了如何在VIVADO软件下封装一个简单的流水灯程序.在ZYNQ开发过程中,有时候我们可能会需要与ARM硬核进行通信,在这 ...

  6. Web API 自动生成接口文档

    1.添加NuGet程序包 Microsoft ASP.NET Web API 2.2 Help Page      (这是微软官方的) A Simple Test Client for ASP.NET ...

  7. 关于ManualResetEvent的实例分析

    最近用WPF开发时使用多个定时器处理时需要实例化N多个DispatcherTimer,而且全部暴露在程序外部,显得很冗杂,例如下面的例子:用到的两个定时器就要实例化两个DispatcherTimer, ...

  8. C#端口、IP正则

    端口正则: string pattrn = "^[0-9]+$"; if (System.Text.RegularExpressions.Regex.IsMatch(Porttex ...

  9. C# 委托 、事件、同步、异步知识点归纳

    一.委托 基本用法: 1.声明一个委托类型.委托就像是‘类'一样,声明了一种委托之后就可以创建多个具有此种特征的委托.(特征,指的是返回值.参数类型) public delegate void Som ...

  10. 很low的四位验证码实现

    <html> <head> <meta charset="utf-8"> </head> <body> <inpu ...