zoukankan      html  css  js  c++  java
  • Gym

    题目:

    思路:

    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("
    ");
        }
        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
    ",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
  • 相关阅读:
    hadoop安装前的准备
    记录一次Qt5程序无法运行的解决过程
    C#里的Thread.Join与Control.Invoke死锁情况
    qbxt7月笔记
    zhxのDP讲
    有n*m的方格图
    最长上升子序列相关问题笔记
    qbxt游记(清北澡堂划水记
    DAZの七下道法(持续更新
    模板
  • 原文地址:https://www.cnblogs.com/sykline/p/9813133.html
Copyright © 2011-2022 走看看