101550A (離線+並查集)
阿新 • • 發佈:2018-12-14
題意:給出一個n*m的方格,剛開始全是白色的方格,每次查詢把一塊區域染成黑色,問白色連通塊的數目有多少
分析:用離線的方法來做,從後往前推的答案,聯通塊用並查集判斷。
程式碼:
#include <map> #include <set> #include <list> #include <cmath> #include <queue> #include <stack> #include <string> #include <cstdio> #include <vector> #include <iomanip> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> #define ll long long #define lowbit(x) (x&(-x)) #define mem(a,b) memset(a,b,sizeof(a)) #define FRER() freopen("in.txt","r",stdin); #define FREW() freopen("out.txt","w",stdout); using namespace std; const int maxn = 1000 + 7; int n,m,q,num; int a[maxn][maxn],f[maxn*maxn],X1[maxn*10],X2[maxn*10],Y1[maxn*10],Y2[maxn*10],res[maxn*10]; const int dx[]={0,0,1,-1}; const int dy[]={1,-1,0,0}; bool ok(int x,int y){ if(1<=x&&x<=n&&1<=y&&y<=m) return true; return false; } int getid(int x,int y){ return (x-1)*m+y; } int Find(int u){ return u==f[u]?u:f[u] = Find(f[u]); } void unite(int x,int y){ //cout<<x<<" "<<y<<endl; int xx = Find(x) , yy = Find(y); if(xx!=yy){ f[xx] = yy; num--; } } void init(){ for(int i=0;i<=n*m;i++) f[i] = i; memset(a, 0, sizeof(a)); } void dfs(int x,int y){ for(int i=0;i<4;i++){ int xx = x+dx[i]; int yy = y+dy[i]; if(ok(xx, yy)&&!a[xx][yy]){ unite(getid(x, y), getid(xx, yy)); } } } int main(){ scanf("%d%d%d",&n,&m,&q); init(); for(int i=1;i<=q;i++){ scanf("%d%d%d%d",&X1[i],&Y1[i],&X2[i],&Y2[i]); if(X1[i]==X2[i]){ for(int j=Y1[i];j<=Y2[i];j++) a[X1[i]][j]++; }else{ for(int j=X1[i];j<=X2[i];j++) a[j][Y1[i]]++; } } num = n*m; for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ if(!a[i][j]) dfs(i,j); else num--; } } for(int i=q;i>=1;i--){ res[i] = num; if(X1[i]==X2[i]){ for(int j=Y1[i];j<=Y2[i];j++){ a[X1[i]][j]--; if(a[X1[i]][j]) continue; num++; dfs(X1[i], j); } }else{ for(int j=X1[i];j<=X2[i];j++){ a[j][Y1[i]]--; if(a[j][Y1[i]]) continue; num++; dfs(j, Y1[i]); } } } for(int i=1;i<=q;i++) printf("%d\n",res[i]); }