CF1303F Number of Components 解题报告
题目来源
这题的思路很明显,但是我太菜了,被奇怪的细节恶心到了😆
看到 \(c_i\le c_{i+1}\) ,很显然的,将元素相同的和一起,分块讨论。
对于一个块,考虑到有两种情况:
- 同元素的联通块的个数,这个正序直接用并查集连接就可以维护了。
- 其他元素的联通块个数,由于是分开讨论,所以不存在和修改的元素相同的元素,考虑倒序,每次恢复时相当于将周围的块联通,可以用并查集维护。
然后就是奇怪的细节问题了,我竟然栽在了求方格的序号上 😂
然后是丑陋的代码:
#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;
}