1. 程式人生 > >101550A (離線+並查集)

101550A (離線+並查集)

題意:給出一個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]);
}