CF1303F Number of Components 解题报告

题目来源
这题的思路很明显,但是我太菜了,被奇怪的细节恶心到了😆
看到 \(c_i\le c_{i+1}\) ,很显然的,将元素相同的和一起,分块讨论。
对于一个块,考虑到有两种情况:

  1. 同元素的联通块的个数,这个正序直接用并查集连接就可以维护了。
  2. 其他元素的联通块个数,由于是分开讨论,所以不存在和修改的元素相同的元素,考虑倒序,每次恢复时相当于将周围的块联通,可以用并查集维护。

然后就是奇怪的细节问题了,我竟然栽在了求方格的序号上 😂
然后是丑陋的代码:

#include<iostream>
#include<cstdio>
using namespace std;

const int M=305,N=2e6+5;

int n,m,q,a[M][M];
int fa[M*M],Fa[M*M],ans[N],Ans[N];
int nxt[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
bool b[M][M];
struct Query{
	int x,y,c,nc;
}Q[N];

int read(){
	int x=0,y=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){
		if(ch=='-') y=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
		x=x*10+ch-'0';
		ch=getchar();
	}
	return x*y;
}

int num(int x,int y){
	return m*(x-1)+y;
}

int find(int x){
	if(x!=fa[x]) fa[x]=find(fa[x]);
	return fa[x];
}

int Find(int x){
	if(x!=Fa[x]) Fa[x]=Find(Fa[x]);
	return Fa[x];
}

void solve(int l,int r){
	for(int i=l;i<=r;i++){
		int x=Q[i].x,y=Q[i].y;
		if(b[x][y]){
			continue ;
		}
		b[x][y]=1;
		ans[i]=1;
		for(int k=0;k<4;k++){
			int nx=x+nxt[k][0],ny=y+nxt[k][1];
			if(nx<1||nx>n||ny<1||ny>m) continue ;
			if(b[nx][ny]){
				int Fx=Find(num(x,y)),Fy=Find(num(nx,ny));
				if(Fx==Fy) continue ;
				ans[i]--;
				Fa[Fx]=Fy;
			}
		}
	}
//	printf("%d %d:",l,r);
//	for(int i=l;i<=r;i++) printf("%d ",ans[i][0]);printf("\n");
	for(int i=l;i<=r;i++){
		int x=Q[i].x,y=Q[i].y;
		b[x][y]=0;
		Fa[num(x,y)]=num(x,y);
	}
	for(int i=r;i>=l;i--){
		int x=Q[i].x,y=Q[i].y;
		if(a[x][y]==Q[i].nc){
			continue ;
		}
		a[x][y]=Q[i].nc;
		ans[i]--;
		fa[num(x,y)]=0;
		for(int k=0;k<4;k++){
			int nx=x+nxt[k][0],ny=y+nxt[k][1];
			if(nx<1||nx>n||ny<1||ny>m) continue ;
			if(a[x][y]==a[nx][ny]){
				if(fa[num(x,y)]==0){
					fa[num(x,y)]=find(num(nx,ny));
					ans[i]++;
					continue ;
				}
				int fx=find(num(x,y)),fy=find(num(nx,ny));
				if(fx==fy) continue ;
				ans[i]++;
				fa[fx]=fy;
			}
		}
		if(fa[num(x,y)]==0){
			fa[num(x,y)]=num(x,y);
		}
	}
//	printf("%d %d:",l,r);
//	for(int i=l;i<=r;i++) printf("%d ",ans[i][1]);printf("\n");
//	for(int i=r;i>=l;i--){
//		if(i==q) continue ;
//		Ans[i]=Ans[i+1]-anss;
//	}
}

int main(){
	n=read(),m=read(),q=read();
	for(int i=1;i<=q;i++){
		Q[i].x=read();
		Q[i].y=read();
		Q[i].c=read();
		Q[i].nc=a[Q[i].x][Q[i].y];
		a[Q[i].x][Q[i].y]=Q[i].c;
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			fa[num(i,j)]=Fa[num(i,j)]=num(i,j);
		}
	}
	Ans[q]=0;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			Ans[q]++;
			for(int k=0;k<4;k++){
				int nx=i+nxt[k][0],ny=j+nxt[k][1];
				if(nx<1||nx>n||ny<1||ny>m) continue ;
				if(a[i][j]==a[nx][ny]){
					int fx=find(num(i,j)),fy=find(num(nx,ny));
					if(fx==fy) continue ;
					Ans[q]--;
					fa[fx]=fy;
				}
			}
		}
	}
//	printf("%d\n",Ans[q]);
	int last=q;
	for(int i=q-1;i>=1;i--){
		if(Q[i].c!=Q[last].c){
			solve(i+1,last);
			last=i;
		}
	}
	solve(1,last);
	for(int i=q-1;i>=1;i--){
		Ans[i]=Ans[i+1]-ans[i+1];
	}
	for(int i=1;i<=q;i++){
		printf("%d\n",Ans[i]);
	}
	return 0;
}
posted @ 2020-08-01 22:13  Dabuliuzp  阅读(149)  评论(0编辑  收藏  举报
/* */ 返回顶端