zoukankan      html  css  js  c++  java
  • Artwork Gym

    题目

      https://cn.vjudge.net/contest/323505#problem/A

    题意

      给出一个m×n的矩阵,一开始全是白色,然后给出q次操作,每次将(x1,y1)到(x2,y2)这宽度为1的区域涂黑。输出每次涂黑操作后白色可以分成多少块。

    题解

      一开始从各种方向去想BFS的优化QAQ,后来才知道是一道并查集的题目。我们可以反向思考,先将每次涂黑的操作进行完毕,每次给涂黑的地方+1,然后把最后状态的白色块用并查集连到一起。那么我们反向删除黑色部分,当删除的这一块权值变为0时,意味着这一块从黑变成白了,那么我们先将其当作独立的一块,记录num++,然后去跑这一点的上下左右,如果两点分属不同的集合,那么num--,并且将外面的点以当前点为父亲连入。每次操作后记录下来答案,最后输出即可。学到了学到了qwq

     #include <iostream>
    #include <cstring>
    #include <string>
    #include <algorithm>
    #include <cmath>
    #include <cstdio>
    #include <queue>
    #include <stack>
    #include <map>
    #include <bitset>
    #define ull unsigned long long
    #define met(a, b) memset(a, b, sizeof(a))
    #define lowbit(x) (x&(-x))
    #define MID (l + r) / 2
    #define ll long long
    
    using namespace std;
    
    const int inf = 0x3f3f3f3f;
    const ll INF = 0x3f3f3f3f3f3f3f3f;
    const ll mod = 1e6 + 3;
    const int maxn = 1e4 + 7;
    const int N = 1010;
    
    struct Que {
        int x1, x2, y1, y2;
    }que[maxn];
    
    int MAP[N][N];
    int dx[] = {0, 0, -1, 1};
    int dy[] = {-1, 1, 0, 0};
    int f[1000100];
    int vis[1000100];
    int res[1000100];
    
    int Find(int i) {return f[i] = (f[i] == i) ? f[i] : f[i] = Find(f[i]);}
    
    int main() {
        int n, m, q;
        cin >> m >> n >> q;
        for(int i = 1; i <= n*m+2; i++) f[i] = i;
        for(int i = 1; i <= q; i++) {
            cin >> que[i].y1 >> que[i].x1 >> que[i].y2 >> que[i].x2;
            if(que[i].x1 == que[i].x2) {
                int t1 = min(que[i].y1, que[i].y2);
                int t2 = max(que[i].y1, que[i].y2); 
                for(int j = t1; j <= t2; j++) MAP[que[i].x1][j]++;
            }
            else {
                int t1 = min(que[i].x1, que[i].x2);
                int t2 = max(que[i].x1, que[i].x2);
                for(int j = t1; j <= t2; j++) MAP[j][que[i].y1]++;
            }
        }
        // for(int i = 1; i <= n; i++) {
        //     for(int j = 1; j <= m; j++) {
        //         cout << MAP[i][j] << ' ';
        //     }
        //     cout << endl;
        // }
        for(int i = 1; i <= n; i++) {
            for(int j = 1; j <= m; j++) {
                if(!MAP[i][j]) {
                    int id = (i-1)*m+j;
                    for(int k = 0; k < 4; k++) {
                        int x = i+dx[k];
                        int y = j+dy[k];
                        if(x < 1 || x > n) continue;
                        if(y < 1 || y > m) continue;
                        if(!MAP[x][y]) {
                            int t = (x-1)*m+y;
                            int fi = Find(id);
                            int fo = Find(t);
                            f[fo] = fi;
                        }
                    }
                }
            }
        }
        int num = 0;
        for(int i = 1; i <= n; i++) {
            for(int j = 1; j <= m; j++) {
                int fi = Find((i-1)*m+j);
                if(!MAP[i][j] && !vis[fi]) {
                    vis[fi] = 1;
                    num++;
                }
            }
        }
        for(int i = q; i >= 1; i--) {
            res[i] = num;
            if(que[i].x1 == que[i].x2) {
                int t1 = min(que[i].y1, que[i].y2);
                int t2 = max(que[i].y1, que[i].y2); 
                for(int j = t1; j <= t2; j++) {
                    MAP[que[i].x1][j]--;
                    if(!MAP[que[i].x1][j]) {
                        num++;
                        int id = (que[i].x1-1)*m+j;
                        for(int k = 0; k < 4; k++) {
                            int x = que[i].x1+dx[k];
                            int y = j+dy[k];
                            if(x < 1 || x > n) continue;
                            if(y < 1 || y > m) continue;
                            if(!MAP[x][y]) {
                                int t = (x-1)*m+y;
                                int fi = Find(id);
                                int fo = Find(t);
                                if(fi != fo) num--;
                                f[fo] = fi;
                            }
                        }
                    }
                }
            }
            else {
                int t1 = min(que[i].x1, que[i].x2);
                int t2 = max(que[i].x1, que[i].x2);
                for(int j = t1; j <= t2; j++) {
                    MAP[j][que[i].y1]--;
                    if(!MAP[j][que[i].y1]) {
                        num++;
                        int id = (j-1)*m+que[i].y1;
                        for(int k = 0; k < 4; k++) {
                            int x = j+dx[k];
                            int y = que[i].y1+dy[k];
                            if(x < 1 || x > n) continue;
                            if(y < 1 || y > m) continue;
                            if(!MAP[x][y]) {
                                int t = (x-1)*m+y;
                                int fi = Find(id);
                                int fo = Find(t);
                                if(fi != fo) num--;
                                f[fo] = fi;
                            }
                        }
                    }
                }
            }
        }
        for(int i = 1; i <= q; i++) cout << res[i] << endl;
        return 0;
    }
  • 相关阅读:
    名门暗战
    redis安装相关下载
    Git:git diff 命令详解
    【教程】Win7-64位安装OpenSSL详细过程
    Linux 下MQ的安装和配置亲测
    用命令创建MySQL数据库
    WebSphere MQ中的CCSID
    Netty:option和childOption参数设置说明
    BeanNameAware接口和BeanFactoryAware接口
    再理解tcp backlog
  • 原文地址:https://www.cnblogs.com/Ruby-Z/p/11455786.html
Copyright © 2011-2022 走看看