2022.02.27 CF811E Vladik and Entertaining Flags
阿新 • • 發佈:2022-04-15
2022.02.27 CF811E Vladik and Entertaining Flags
https://www.luogu.com.cn/problem/CF811E
Step 1 題意
在一個 n*m 的網格上每個格子都有顏色,q 次詢問,每次詢問只保留 l 至 r 列時有多少個四連通的顏色塊。兩個格子同色但不連通算在不同的顏色塊內。
Step 2 分析
這道題我首先大力找到一個錯誤規律,這個暫且不說,直接上正解。
對於每一列的格子搞線段樹,記錄每列有幾個連通塊,每列的最左側和最右側的節點屬於哪個連通塊。
合併的時候合併兩個連通塊相鄰的兩列,如果顏色一致並且fa不一樣,總連通塊的數量減一。不過需要初始化一下相鄰兩列格子的並查集。
Step 3 程式碼如下
#include<bits/stdc++.h> using namespace std; const int N=1e5+10; int n,m,q,mapi[15][N],fa[N*15]; int tot; struct node{ int x,y,L[15],R[15],sum; }t[N<<4]; inline int read(){ int s=0,w=1; char ch=getchar(); while(ch<'0'||ch>'9'){ if(ch=='-')w=-1; ch=getchar(); } while(ch<='9'&&ch>='0'){ s=s*10+ch-'0'; ch=getchar(); } return s*w; } inline int find(int x){ return x==fa[x]?x:fa[x]=find(fa[x]); } inline node update(node x,node y,int l,int r){ node ans; ans.sum=x.sum+y.sum; for(int i=1;i<=n;i++) fa[x.L[i]]=x.L[i],fa[x.R[i]]=x.R[i], fa[y.L[i]]=y.L[i],fa[y.R[i]]=y.R[i]; for(int i=1;i<=n;i++)ans.L[i]=x.L[i],ans.R[i]=y.R[i]; for(int i=1;i<=n;i++) if(mapi[i][l]==mapi[i][r]){ int xi=find(fa[x.R[i]]); int yi=find(fa[y.L[i]]); if(xi!=yi)fa[xi]=yi,--ans.sum; } for(int i=1;i<=n;i++) ans.L[i]=find(ans.L[i]),ans.R[i]=find(ans.R[i]); return ans; } inline void build(int x,int l,int r){ if(l==r){ for(int i=1;i<=n;i++) if(mapi[i][l]==mapi[i-1][l]) t[x].L[i]=t[x].R[i]=t[x].L[i-1]; else t[x].L[i]=t[x].R[i]=++tot,++t[x].sum; return ; } int mid=(l+r)>>1; build(x<<1,l,mid); build(x<<1|1,mid+1,r); t[x]=update(t[x<<1],t[x<<1|1],mid,mid+1); } inline node query(int x,int l,int r,int L,int R){ if(l>=L&&r<=R)return t[x]; int mid=(l+r)>>1; int flaga=0,flagb=0; node a,b,ans; if(L<=mid)a=query(x<<1,l,mid,L,R),flaga=1; if(R>mid)b=query(x<<1|1,mid+1,r,L,R),flagb=1; if(flaga&&!flagb)ans=a; else if(flagb&&!flaga)ans=b; else if(flaga&&flagb)ans=update(a,b,mid,mid+1); return ans; } signed main(){ n=read();m=read();q=read(); for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)mapi[i][j]=read(); //cout<<"Case 1 "<<endl; build(1,1,m); //cout<<"Case 2 "<<endl; for(int i=1;i<=q;i++){ int u,v; u=read();v=read(); node fin=query(1,1,m,u,v); cout<<fin.sum<<endl; } return 0; }