hdu 4419 Colourful Rectangle (离散化扫描线线段树)

Problem - 4419

  题意不难,红绿蓝三种颜色覆盖在平面上,不同颜色的区域相交会产生新的颜色,求每一种颜色的面积大小。

  比较明显,这题要从矩形面积并的方向出发。如果做过矩形面积并的题,用线段树做的,这题就只差一个把每个区域计算单独出来的思路了。

  这里不详细介绍扫描线,只是说一下针对这题的做法。其实网上有好多版本,都是直接单独计算答案的。然而,我稍微绕了个小弯,我觉得我这种处理方法也是比较容易想到以及实现的。如果我们用7棵线段树计算R、G、B、R||G、R||B、B||G、R||G||B这7种情况,我们并不能直接得到所要的答案。不过可以知道,ans(G)=S(R||G||B)-S(R||B)的(这里的||是两种颜色的面积并的意思)。同理我们可以得到ans(B)、ans(R)。然后根据这个,我们可以得到ans(RB)=S(R||G||B)-ans(R)-ans(B)-S(G)。同理可以得到ans(RG),ans(GB)。最后就只剩ans(RGB)了。

代码如下:

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <map>
  4 #include <iostream>
  5 #include <algorithm>
  6 
  7 using namespace std;
  8 
  9 map<char, int> id;
 10 void preMap() {
 11     id['R'] = 0;
 12     id['G'] = 1;
 13     id['B'] = 2;
 14 }
 15 
 16 const int N = 22222;
 17 const int K = 1 << 3;
 18 map<int, int> xid;
 19 int rx[N], xn;
 20 
 21 struct Node {
 22     int id, x1, x2, y;
 23     bool end;
 24     Node() {}
 25     Node(int id, int x1, int x2, int y, bool end)
 26         : id(id), x1(x1), x2(x2), y(y), end(end) {}
 27 } node[N];
 28 
 29 void input(int n) {
 30     char buf[3];
 31     int a, b, c, d;
 32     for (int i = 0; i < n; i++) {
 33         scanf("%s%d%d%d%d", buf, &a, &b, &c, &d);
 34         if (a > c) swap(a, c);
 35         if (b > d) swap(b, d);
 36         rx[i << 1] = a;
 37         rx[i << 1 | 1] = c;
 38         node[i << 1] = Node(id[buf[0]], a, c, b, false);
 39         node[i << 1 | 1] = Node(id[buf[0]], a, c, d, true);
 40     }
 41     n <<= 1;
 42     sort(rx, rx + n);
 43     xn = unique(rx, rx + n) - rx;
 44 //    for (int i = 0; i < xn; i++) cout << rx[i] << ' '; cout << endl;
 45     xid.clear();
 46     for (int i = 0; i < xn; i++) xid[rx[i]] = i;
 47     for (int i = 0; i < n; i++) {
 48         node[i].x1 = xid[node[i].x1];
 49         node[i].x2 = xid[node[i].x2];
 50     }
 51 }
 52 
 53 #define lson l, m, rt << 1
 54 #define rson m + 1, r, rt << 1 | 1
 55 #define root 0, xn - 1, 1
 56 
 57 int sum[K][N << 2];
 58 int mk[K][N << 2];
 59 int cur;
 60 
 61 void up(int rt, int l, int r) {
 62     if (mk[cur][rt]) sum[cur][rt] = rx[r + 1] - rx[l];
 63     else sum[cur][rt] = sum[cur][rt << 1] + sum[cur][rt << 1 | 1];
 64 }
 65 
 66 void build(int l, int r, int rt) {
 67     sum[cur][rt] = mk[cur][rt] = 0;
 68     if (l == r) return ;
 69     int m = l + r >> 1;
 70     build(lson);
 71     build(rson);
 72 }
 73 
 74 void update(int k, int L, int R, int l, int r, int rt) {
 75     if (L <= l && r <= R) {
 76         mk[cur][rt] += k;
 77         if (l != r) up(rt, l, r);
 78         else {
 79             if (mk[cur][rt]) sum[cur][rt] = rx[r + 1] - rx[l];
 80             else sum[cur][rt] = 0;
 81         }
 82         return ;
 83     }
 84     int m = l + r >> 1;
 85     if (L <= m) update(k, L, R, lson);
 86     if (m < R) update(k, L, R, rson);
 87     up(rt, l, r);
 88 }
 89 
 90 bool cmp(Node a, Node b) { return a.y < b.y || a.y == b.y && a.end < b.end;}
 91 
 92 typedef long long LL;
 93 
 94 void work(int n) {
 95     n <<= 1;
 96     LL tt[K];
 97     memset(tt, 0, sizeof(tt));
 98     sort(node, node + n, cmp);
 99     if (node[0].end) { puts("shit!!"); while (1) ;}
100     for (cur = 0; cur < K; cur++) {
101         build(root);
102         if (cur & 1 << node[0].id) update(1, node[0].x1, node[0].x2 - 1, root);
103     }
104     for (int i = 1; i < n; i++) {
105         for (cur = 0; cur < K; cur++) {
106             if (sum[cur][1] < 0 || sum[cur][1] > 1e9) { puts("shit!!!"); while (1) ;}
107             tt[cur] += (LL) sum[cur][1] * (node[i].y - node[i - 1].y);
108             if (cur & (1 << node[i].id)) update(node[i].end ? -1 : 1, node[i].x1, node[i].x2 - 1, root);
109         }
110 //        for (int i = 0; i < K; i++) cout << tt[i] << ' '; cout << endl;
111     }
112     LL sgl[3], dbl[3], lst = tt[K - 1];
113     for (int i = 0; i < 3; i++) {
114         sgl[i] = tt[K - 1] - tt[(K - 1) ^ (1 << i)];
115         lst -= sgl[i];
116         cout << sgl[i] << endl;
117     }
118     for (int i = 0; i < 3; i++) {
119         dbl[i] = tt[K - 1];
120         for (int j = 0; j < 3; j++) {
121             if (i != j) dbl[i] -= sgl[j];
122             else dbl[i] -= tt[1 << j];
123         }
124         lst -= dbl[i];
125     }
126     for (int i = 2; i >= 0; i--) cout << dbl[i] << endl;
127     cout << lst << endl;
128 }
129 
130 int main() {
131 //    freopen("in", "r", stdin);
132     preMap();
133     int T, n;
134     scanf("%d", &T);
135     for (int cas = 1; cas <= T; cas++) {
136         scanf("%d", &n);
137         input(n);
138         printf("Case %d:
", cas);
139         work(n);
140     }
141     return 0;
142 }
View Code

  感觉这种方法写起来不会吃力,就是计算上面会稍微需要思考。不过我还是因为把xid写成xd导致wa了一个晚上。_(囧」∠)_

——written by Lyon

原文地址:https://www.cnblogs.com/LyonLys/p/hdu_4419_Lyon.html