计蒜客 A.Artwork 并查集+set

版权声明:本文为博主原创文章,转载标明出处。 https://blog.csdn.net/xlzhang223/article/details/78156759

链接:点击打开链接

题意:画直线分区域,问每画完一条线有几个区域

思路:倒着做变成擦直线,合并区域或形成新区域。可以使用并查集来维护。启发:类似拆分的问题都可以倒过来离线变成合并的问题。

代码:

#include<bits/stdc++.h>
#define LL long long
#define PB push_back
#define pii pair<int,int>
#define MP make_pair
#define X first
#define Y second
using  namespace std;
typedef long long ll;
const int maxn=2e6+10;
pii f[10004],s[10004];
int mp[1005][1005];
int fa[maxn];
set<int> ST;
int fin(int x){
    if(fa[x]==x)return x;
    fa[x]=fin(fa[x]);
    return fa[x];
}

void combin(int x,int y){
    int fx=fin(x),fy=fin(y);
    if(fx!=fy){
        fa[fx]=fy;
        if(ST.find(fx)!=ST.end()){
            ST.erase(ST.find(fx));
        }
        ST.insert(fy);
    }
    return;
}

int hs(int x,int y){
    return x*1000+y-1;
}

void up(int xx,int yy){
    ST.insert(hs(xx,yy));
    if(mp[xx+1][yy]==0) combin(hs(xx,yy),hs(xx+1,yy));
    if(mp[xx-1][yy]==0) combin(hs(xx,yy),hs(xx-1,yy));
    if(mp[xx][yy+1]==0) combin(hs(xx,yy),hs(xx,yy+1));
    if(mp[xx][yy-1]==0) combin(hs(xx,yy),hs(xx,yy-1));
    if(fin(hs(xx,yy))!=hs(xx,yy)&&ST.find(hs(xx,yy))!=ST.end()) ST.erase(ST.find(hs(xx,yy)));
}

int main(){
    int n,m,q;
    scanf("%d%d%d",&n,&m,&q);
    for(int i=0;i<maxn;i++) fa[i]=i;
    for(int i=0;i<q;i++){
        scanf("%d%d%d%d",&f[i].X,&f[i].Y,&s[i].X,&s[i].Y);
        if(f[i].X==s[i].X){
            if(f[i].Y>s[i].Y) swap(s[i],f[i]);
            for(int j=f[i].Y;j<=s[i].Y;j++) ++mp[f[i].X][j];
        }
        else{
            if(f[i].X>s[i].X) swap(s[i],f[i]);
            for(int j=f[i].X;j<=s[i].X;j++) ++mp[j][f[i].Y];
        }
    }
    for(int i=0;i<=n+1;i++) mp[i][m+1]=mp[i][0]=1;
    for(int i=0;i<=m+1;i++) mp[n+1][i]=mp[0][i]=1;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            if(mp[i][j]==0)up(i,j);
    vector<int> ans;
    for(int i=q-1;i>=0;i--){
        ans.PB(ST.size());
        if(f[i].X==s[i].X){
            if(f[i].Y>s[i].Y) swap(s[i],f[i]);
            for(int j=f[i].Y;j<=s[i].Y;j++){
                --mp[f[i].X][j];
                if(mp[f[i].X][j]==0) up(f[i].X,j);
            }
        }
        else{
            if(f[i].X>s[i].X) swap(s[i],f[i]);
            for(int j=f[i].X;j<=s[i].X;j++){
                --mp[j][f[i].Y];
                if(mp[j][f[i].Y]==0)up(j,f[i].Y);
            }
        }
    }
    reverse(ans.begin(),ans.end());
    for(int a:ans) printf("%d\n",a);
    return 0;
}


猜你喜欢

转载自blog.csdn.net/xlzhang223/article/details/78156759
今日推荐