码迷,mamicode.com
首页 > 其他好文 > 详细

Gym - 101550A(Artwork 倒序+并查集)

时间:2018-10-18 22:12:10      阅读:224      评论:0      收藏:0      [点我收藏+]

标签:过程   sid   答案   合并   png   分享   str   div   pre   

题目:

技术分享图片

思路:

1、对输入数据离线,先把所有的黑线都画出来,统计一下剩余的白色连通块的个数,dfs过程将一个连通块放到一个集合中。

2、倒着往前消去黑线,如果当前的块A是白块就看他的四周有没有白块:有白块B,看A和B的祖先是不是一样,一样的话pass,否则合并连通块并且白色连通块的数目减一(当然第一个是跳过的)。四周全是黑块的话,白色连通块的数量加一。

3、用栈存储一下每一步的答案,最后输出就可以了。

PS:看错了q的数据范围,卡了三天,话说前两天答案状态是WA在test5,第三天就成了memor limit exceeded,然后就发现自己的错误了。菜是原罪啊!!

代码:

技术分享图片
#include <bits/stdc++.h>
#define inf 1e9
#define FRE() freopen("in.txt","r",stdin)
using namespace std;
typedef long long ll;
const ll MOD = 2147493647;
const int maxn = 1e3+10;
int mp[maxn][maxn],fa[maxn*maxn],vis[maxn][maxn];
int dir[4][2] = {{1,0},{-1,0},{0,1},{0,-1}};
struct label
{
    int r1,c1;
    int r2,c2;
} l[maxn*10];
int r,c,q,num_white;

int getId(int x,int y)
{
    return x*c+y;
}


void init()
{
    num_white = 0;
    memset(mp,0,sizeof(mp));
    memset(vis,0,sizeof(vis));
    for(int i = 0; i<maxn*maxn; i++)
    {
        fa[i] = i;
    }
    return;
}

int Find(int x)
{
    return fa[x]==x ? x : fa[x] = Find(fa[x]);
}

void input()
{
    int x1,x2,y1,y2;
    for(int i = 0; i<q; i++)
    {
        scanf("%d%d%d%d",&l[i].c1,&l[i].r1,&l[i].c2,&l[i].r2);
        l[i].c1--,l[i].c2--,l[i].r1--,l[i].r2--;
        if(l[i].r1==l[i].r2)
        {
            int x = l[i].r1;
            for(int j = l[i].c1; j<=l[i].c2; j++)
                mp[x][j]++;
        }
        else if(l[i].c1==l[i].c2)
        {
            int y = l[i].c2;
            for(int j = l[i].r1; j<=l[i].r2; j++)
                mp[j][y]++;
        }
    }
}

bool inside(int x,int y)
{
    if(x>=0 && x<r && y>=0 && y<c)
        return true;
    return false;
}

void dfs(int x,int y,int iid)
{
    int id = getId(x,y);
    vis[x][y] = 1;
    fa[id] = iid;
    for(int i = 0; i<4; i++)
    {
        int tx = x+dir[i][0],ty = y+dir[i][1];
        if(inside(tx,ty) && !mp[tx][ty] && !vis[tx][ty])
        {
            dfs(tx,ty,iid);
        }
    }
    return;
}

bool _union(int x,int y)
{
    int tx = Find(x),ty = Find(y);
    if(tx!=ty)
    {
        fa[tx] = ty;
        return true;
    }
    return false;
}

void solve(int x,int y)
{
    int f = 0,isfirst = 0;
    for(int i = 0; i<4; i++)
    {
        int tx = x+dir[i][0],ty = y+dir[i][1];
        if(inside(tx,ty))
        {
            if(!mp[tx][ty])
            {
                f = 1;
                if(_union(getId(x,y),getId(tx,ty)))
                {
                    isfirst++;
                    if(isfirst == 1)
                        continue;
                    else
                        num_white--;
                }
            }
        }
    }
    if(!f)
        num_white++;
}

void check()
{
    for(int i = 0; i<r; i++)
    {
        for(int j = 0; j<c; j++)
        {
            printf("%d ",mp[i][j]);
        }
        printf("\n");
    }
    cout<<"GG"<<endl;
}

void countWhite()
{
    for(int i = 0; i<r; i++)
    {
        for(int j = 0; j<c; j++)
        {
            int id = getId(i,j);
            if(!mp[i][j] && !vis[i][j])
            {
                dfs(i,j,id);
                num_white++;
            }
        }
    }
}


int main()
{
    //FRE();
    scanf("%d%d%d",&c,&r,&q);
    init();
    input();
    countWhite();
    stack<int> ans;
    for(int i = q-1; i>=0; i--)
    {
        ans.push(num_white);
        int x1 = l[i].r1,x2=l[i].r2,y1=l[i].c1,y2=l[i].c2;
        if(x1==x2)
        {
            for(int j=y1; j<=y2; j++)
            {
                mp[x1][j]--;
                if(mp[x1][j]==0)
                {
                    solve(x1,j);
                }
            }
        }
        else if(y1==y2)
        {
            for(int j=x1; j<=x2; j++)
            {
                mp[j][y1]--;
                if(mp[j][y1]==0)
                {
                    solve(j,y1);
                }
            }
        }
        //check();
    }
    while(!ans.empty())
    {
        printf("%d\n",ans.top());
        ans.pop();
    }
    return 0;
}
/*
4 6 5
2 2 2 6
1 3 4 3
2 5 3 5
4 6 4 6
1 6 4 6
*/
/*
1
3
3
4
3
*/
View Code

 

Gym - 101550A(Artwork 倒序+并查集)

标签:过程   sid   答案   合并   png   分享   str   div   pre   

原文地址:https://www.cnblogs.com/sykline/p/9813133.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!