[WC2005]双面棋盘
description
洛谷
给出一个\(n\times n\)的黑白棋盘。
\(m\)次操作,每次将一个格子进行颜色翻转,求每次操作后的黑白四连通块数。
data range
\]
solution
解决动态维护图连通性的方法有2种:
一种是通过\(LCT\)动态维护最大删边时间生成树,另一种是线段树分治。
所以当然线段树分治更好写不是吗反正不会LCT的做法。
然后稍稍讨论一波就完了
Code
#include<bits/stdc++.h>
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<iomanip>
#include<cstring>
#include<complex>
#include<vector>
#include<cstdio>
#include<string>
#include<bitset>
#include<ctime>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#define F "a"
#define mp make_pair
#define pb push_back
#define RG register
#define il inline
using namespace std;
typedef unsigned long long ull;
typedef pair<int,int> PI;
typedef vector<int>VI;
typedef long long ll;
typedef double dd;
const int N=2e2+10;
const int K=4e4+10;
const int mod=998244353;
const int inf=2147483647;
const ll INF=1ll<<60;
const dd eps=1e-7;
const dd pi=acos(-1);
il ll read(){
RG ll data=0,w=1;RG char ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')w=-1,ch=getchar();
while(ch<='9'&&ch>='0')data=data*10+ch-48,ch=getchar();
return data*w;
}
il void file(){
freopen(F".in","r",stdin);
freopen(F".out","w",stdout);
}
int n,m,p[N][N],cnt,c[N][N],v[N][N],b,w;VI a[N][N];bool vis[N][N];
struct node{int x,y,c;}now;
vector<node>M[K];
#define ls (i<<1)
#define rs (i<<1|1)
#define mid ((l+r)>>1)
void modify(int i,int l,int r,int x,int y){
if(x<=l&&r<=y){M[i].push_back(now);return;}
if(x<=mid)modify(ls,l,mid,x,y);
if(mid<y)modify(rs,mid+1,r,x,y);
}
int dx[]={0,1,0,-1},dy[]={1,0,-1,0};
struct Mod{int id,u,v;};vector<Mod>cal;
int nowid,top;
int fa[K];
int find(int x){
if(!fa[x])return x;
RG int ff=find(fa[x]);
if(fa[x]!=ff){cal.push_back((Mod){nowid,x,fa[x]});top++;}
return fa[x]=ff;
}
il void merge(int x,int y){
x=find(x);y=find(y);if(x==y)return;
cal.push_back((Mod){nowid,x,fa[x]});top++;
fa[x]=y;
}
#define pd(i,j) (i<1||i>n||j<1||j>n||!vis[i][j])
set<int>S;
il void insert(int x,int y,int col){
vis[x][y]=1;c[x][y]=col;nowid=p[x][y];
S.clear();
for(RG int k=0,xx,yy;k<4;k++){
xx=x+dx[k];yy=y+dy[k];if(pd(xx,yy))continue;
if(c[xx][yy]==c[x][y]){
S.insert(find(p[xx][yy]));
merge(p[x][y],p[xx][yy]);
}
}
v[x][y]=1-S.size();col?b+=v[x][y]:w+=v[x][y];
}
il void undo(int x,int y){
nowid=p[x][y];
while(top&&cal[top-1].id==nowid)
fa[cal[top-1].u]=cal[top-1].v,cal.pop_back(),top--;
c[x][y]?b-=v[x][y]:w-=v[x][y];vis[x][y]=0;
}
void divide(int i,int l,int r){
RG int sz=M[i].size();
for(RG int k=0;k<sz;k++)
insert(M[i][k].x,M[i][k].y,M[i][k].c);
if(l==r)printf("%d %d\n",b,w);
else{divide(ls,l,mid);divide(rs,mid+1,r);}
for(RG int k=sz-1;~k;k--)
undo(M[i][k].x,M[i][k].y);
}
int main()
{
n=read();
for(RG int i=1;i<=n;i++)
for(RG int j=1;j<=n;j++)
{p[i][j]=++cnt;c[i][j]=read()^1;a[i][j].push_back(1);}
m=read();
for(RG int i=1,x,y;i<=m;i++){
x=read();y=read();a[x][y].push_back(i);
}
for(RG int i=1;i<=n;i++)
for(RG int j=1;j<=n;j++)
a[i][j].push_back(m+1);
for(RG int i=1;i<=n;i++)
for(RG int j=1;j<=n;j++)
for(RG int k=0,sz=a[i][j].size();k<sz-1;k++){
c[i][j]^=1;now=(node){i,j,c[i][j]};
if(a[i][j][k]!=a[i][j][k+1])
modify(1,1,m,a[i][j][k],a[i][j][k+1]-1);
}
divide(1,1,m);
return 0;
}
[WC2005]双面棋盘的更多相关文章
- P4121 [WC2005]双面棋盘
题目 P4121 [WC2005]双面棋盘 貌似是刘汝佳出的题目?? 做法 线段树维护并查集 线段树分治\(1\)~\(n\)行,我们要考虑维护的肯定是黑.白各自的联通块数量 考虑区间合并,其实就与中 ...
- 【题解】Luogu P4121 [WC2005]双面棋盘
原题传送门 这道题肥肠毒瘤qwqwq,我被卡了qwqwq 这题的正解好像是线段树+并查集,但由于我人丑常数大被卡成了70 #include <bits/stdc++.h> #define ...
- [WC2005]双面棋盘(并查集+分治)
题目描述 题解 唉,还是码力不行,写了一个多小时发现想错了又重构了一个多小时. 这道题意图很显然,动态维护联通块,有一个经典做法就是用LCT维护按照删除时间维护的最大生成树. 网上还有一种神奇的做法, ...
- [WC2005]双面棋盘(线段树+并查集)
线段树+并查集维护连通性. 好像 \(700ms\) 的时限把我的常数超级大的做法卡掉了, 必须要开 \(O_2\) 才行. 对于线段树的每一个结点都开左边的并查集,右边的并查集,然后合并. \(Co ...
- 洛谷P4121 [WC2005]双面棋盘(线段树套并查集)
传送门 先膜一下大佬->这里 据说这题正解是LCT,然而感觉还是线段树套并查集的更容易理解 我们对于行与行之间用线段树维护,每一行内用并查集暴力枚举 每一行内用并查集暴力枚举连通块这个应该容易理 ...
- 【BZOJ1453】[Wc]Dface双面棋盘 线段树+并查集
[BZOJ1453][Wc]Dface双面棋盘 Description Input Output Sample Input Sample Output HINT 题解:话说看到题的第一反应其实是LCT ...
- bzoj 1453: [Wc]Dface双面棋盘
1453: [Wc]Dface双面棋盘 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 617 Solved: 317[Submit][Status][ ...
- BZOJ1453: [WC2005]Dface双面棋盘
离线LCT维护MST,和3082的方法一样.然而比较码农,适合颓废的时候写. PS:线段树分治要好写得多,LCT比较自娱自乐. #include<bits/stdc++.h> using ...
- 【BZOJ1453】[WC] Dface双面棋盘(LCT维护联通块个数)
点此看题面 大致题意: 给你一个\(n*n\)的黑白棋盘,每次将一个格子翻转,分别求黑色连通块和白色连通块的个数. \(LCT\)动态维护图连通性 关于这一部分内容,可以参考这道例题:[BZOJ402 ...
随机推荐
- Adobe Photoshop CC2018最新教程+某宝店铺装修教程
PS免费教程,ps淘宝店铺装修教程.该资源为本人从某商网站重金买来,现免费分享给大家,下载地址:百度网盘,https://pan.baidu.com/s/127PjFbGwVVUVce1litHFsw
- 「日常训练」 Longest Run on a Snowboard (UVA-10285)
题意 其实就是一条二维的LIS,但是还是做的一愣一愣的,多努力. 考虑$dp[i][j]$为从(i,j)出发的二维LIS的最大值,那么$dp[i][j]=max\{dp[i−di[k]][j−dj[k ...
- 运用GamePlayKit的GKEntity及GKComponent 的iOS游戏开发实例
GameplayKit是一个面向对象的框架,为构建游戏提供基础工具和技术. GameplayKit包含用于设计具有功能性,可重用架构的游戏的工具,以及用于构建和增强诸如角色移动和对手行为的游戏玩法特征 ...
- [JSON].toXMLString()
语法:[JSON].toXMLString() 返回:[String] 说明:将[JSON]实例转换成XML格式结果. 示例: <% jsonString = "{div: 'hell ...
- Ubuntu16.04安装wps办公软件解决文字缺失
先到wps官网下载linux版wps安装包 选择64位的alpha版本下载: 下载完后,同样是cd到Downloads目录,用dpkg命令来安装它: cd Downloads/ sudo dpkg ...
- 解决python中文编码错误问题
对于初学者而言,编码问题或许还没有没重视起来,但是编码问题是中文开发者必须面对的.今天来看下python开发中如何解决编码问题.注意:本篇讲的是最常见的一种编码问题,其他编码问题,如json函数引起的 ...
- object-oriented 第二次作业(2)
面向对象程序设计自学计划 由于我的英文实在是很差,所以我就没有去考虑看英文的课程视频.网络上的课程有很多,什么学校的也有,一开始我不知道该如何开始选择课程.感觉每个都还可以.后来在群里的看到别人推荐的 ...
- 项目选题报告(I konw)
一.团队成员及分工 团队名称:I know 团队成员: 陈家权:选题报告word撰写 赖晓连:ppt制作,原型设计 雷晶:ppt制作,原型设计 林巧娜:原型设计,博客随笔撰写 庄加鑫:选题报告word ...
- ACM 第八天
数据结构和算法目录表 数据结构和算法目录表 C C++ Java 线性结构 1. 数组.单链表和双链表 2. Linux内核中双向链表的经典实现 数组.单链表和双链表 数组.单链表和双链表 ...
- lintcode-141-x的平方根
141-x的平方根 实现 int sqrt(int x) 函数,计算并返回 x 的平方根. 样例 sqrt(3) = 1 sqrt(4) = 2 sqrt(5) = 2 sqrt(10) = 3 挑战 ...