Artwork Gym - 101550A 离线并查集

题目:题目链接

思路:每个空白区域当作一个并查集,因为正着使用并查集分割的话dfs会爆栈,判断过于复杂也会导致超时,我们采用离线反向操作,先全部涂好,然后把黑格子逐步涂白,我们把每个空白区域当作一个并查集,然后采用合并并查集的方法来做,好困啊,明天还有课,具体思路有空再写吧,先睡觉了。

AC代码:

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <algorithm>
  5 #include <vector>
  6 
  7 using namespace std;
  8 
  9 #define y1 yy1
 10 #define y2 _y2
 11 
 12 const int maxn = 1000 + 5;
 13 const int maxq = 10000 + 5;
 14     
 15 int grid[maxn][maxn], x1[maxq], y1[maxq], x2[maxq], y2[maxq], num[maxn * maxn], n, m, q, sum, ans[maxq];
 16 
 17 int cx[] = { -1, 0, 1, 0 };
 18 int cy[] = { 0, -1, 0, 1 };
 19 
 20 void init();
 21 int cal(int, int);
 22 bool judge(int, int);
 23 void unite(int, int);
 24 int _find(int);
 25 void solve();
 26 
 27 int main()
 28 {
 29     ios::sync_with_stdio(0);
 30     cin.tie(0);
 31 
 32     cin >> n >> m >> q;
 33 
 34     for (int i = 1; i <= q; ++i) {
 35         cin >> x1[i] >> y1[i] >> x2[i] >> y2[i];
 36         if (x1[i] == x2[i])
 37             for (int j = y1[i]; j <= y2[i]; ++j)
 38                 ++grid[x1[i]][j];
 39         else
 40             for (int j = x1[i]; j <= x2[i]; ++j)
 41                 ++grid[j][y1[i]];
 42     }
 43 
 44     init();
 45 
 46     solve();
 47 
 48     for (int i = 1; i <= q; ++i)
 49         cout << ans[i] << endl;
 50 
 51     return 0;
 52 }
 53 
 54 void init() {
 55     for (int i = 0; i <= n * m; ++i)
 56         num[i] = i;
 57 
 58     sum = n * m;
 59 
 60     for (int i = 1; i <= n; ++i) {
 61         for (int j = 1; j <= m; ++j) {
 62             if (!grid[i][j]) {
 63                 for (int k = 0; k < 4; ++k) {
 64                     if (judge(i + cx[k], j + cy[k]) && !grid[i + cx[k]][j + cy[k]]) {
 65                         unite(cal(i, j), cal(i + cx[k], j + cy[k]));
 66                     }
 67                 }
 68             }
 69             else 
 70                 --sum;
 71         }
 72     }
 73 }
 74 
 75 int cal(int x, int y) {
 76     return (x - 1) * m + y;
 77 }
 78 
 79 bool judge(int x, int y) {
 80     return x > 0 && x <= n && y > 0 && y <= m;
 81 }
 82 
 83 void unite(int x, int y) {
 84     int a = _find(x), b = _find(y);
 85     if (a == b)
 86         return;
 87 
 88     --sum;
 89     num[a] = b;
 90 }
 91 
 92 int _find(int x) {
 93     return x == num[x] ? x : num[x] = _find(num[x]);
 94 }
 95 
 96 void solve() {
 97     for (int i = q; i > 0; --i) {
 98         ans[i] = sum;
 99         if (x1[i] == x2[i]) {
100             for (int j = y1[i]; j <= y2[i]; ++j) {
101                 --grid[x1[i]][j];
102                 if (!grid[x1[i]][j]) {
103                     ++sum;
104                     for (int k = 0; k < 4; ++k) {
105                         if (judge(x1[i] + cx[k], j + cy[k]) && !grid[x1[i] + cx[k]][j + cy[k]])
106                             unite(cal(x1[i], j), cal(x1[i] + cx[k], j + cy[k]));
107                     }
108                 }
109             }
110         }
111         else {
112             for (int j = x1[i]; j <= x2[i]; ++j) {
113                 --grid[j][y1[i]];
114                 if (!grid[j][y1[i]]) {
115                     ++sum;
116                     for (int k = 0; k < 4; ++k)
117                         if (judge(j + cx[k], y1[i] + cy[k]) && !grid[j + cx[k]][y1[i] + cy[k]])
118                             unite(cal(j, y1[i]), cal(j + cx[k], y1[i] + cy[k]));
119                 }
120             }
121         }
122     }
123 }

猜你喜欢

转载自www.cnblogs.com/fan-jiaming/p/9764078.html
今日推荐