感谢YB,CQ。
用线段树算出7种不同颜色的矩形面积并集,然后容斥原理分别算出每块单独颜色的面积。
这里的线段树写法比较特殊,只需要修改操作,查询的结果在1那个节点那里,重点是pushUp,因为这里扫描线求矩形面积并是一种特殊区间修改(保证随时都大于0,相同区间至少会有2个,一个下边,一个上边,所以可以不用像一般的区间修改线段树一样带Lazy标记的同时需要pushDown),标记当前区间是否存在,不存在就访问左右孩子。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include <stdio.h> 2 #include <string.h> 3 #include <algorithm> 4 #include <iostream> 5 #define lld "%I64d\n" 6 using namespace std; 7 typedef long long ll; 8 const int maxn = 1e4 + 4; 9 int T, n, sc, xc, X[maxn << 1], a[maxn << 1]; 10 struct segment { 11 int l, r, h, c, d, lid, rid; 12 segment(int l = 0, int r = 0, int h = 0, int c = 0, int d = 0) : l(l), r(r), h(h), c(c), d(d) {} 13 }segs[maxn << 1]; 14 #define m ((l + r) >> 1) 15 #define lc o << 1 16 #define rc lc | 1 17 int ql, qr, val, sum[maxn << 3], mark[maxn << 3]; 18 inline void pushUp(int o, int l, int r) { 19 if (mark[o]) 20 sum[o] = X[r] - X[l - 1]; 21 else if (l == r) 22 sum[o] = 0; 23 else 24 sum[o] = sum[lc] + sum[rc]; 25 } 26 inline void modify(int o, int l, int r) { 27 if (ql <= l && r <= qr) { 28 mark[o] += val; 29 pushUp(o, l, r); 30 } else { 31 if (ql <= m) 32 modify(lc, l, m); 33 if (m < qr) 34 modify(rc, m + 1, r); 35 pushUp(o, l, r); 36 } 37 } 38 int main() { 39 scanf("%d", &T); 40 for (int Tc = 1; Tc <= T; ++Tc) { 41 scanf("%d", &n); 42 sc = xc = 0; 43 for (int i = 0; i < n; ++i) { 44 int x1, x2, y1, y2, c; 45 char color[4]; 46 scanf("%s%d%d%d%d", color, &x1, &y1, &x2, &y2); 47 switch (color[0]) { 48 case 'R' : c = 1; break; 49 case 'G' : c = 2; break; 50 case 'B' : c = 4; break; 51 } 52 segs[sc++] = segment(x1, x2, y1, c, 1); 53 segs[sc++] = segment(x1, x2, y2, c, -1); 54 X[xc++] = x1; 55 X[xc++] = x2; 56 a[sc - 1] = sc - 1; 57 a[sc - 2] = sc - 2; 58 } 59 sort(a, a + sc, [](int x, int y) { return segs[x].h < segs[y].h; } ); 60 sort(X, X + xc); 61 xc = unique(X, X + xc) - X; 62 for (int i = 0; i < sc; ++i) { 63 segment &s = segs[i]; 64 s.lid = lower_bound(X, X + xc, s.l) - X + 1; 65 s.rid = lower_bound(X, X + xc, s.r) - X; 66 } 67 ll _[8]; 68 memset(_, 0, sizeof(_)); 69 for (int st = 1; st < 8; ++st) { 70 memset(sum , 0, sizeof(int) * (xc << 2)); 71 memset(mark , 0, sizeof(int) * (xc << 2)); 72 ll &ans = _[st]; 73 int last = -1; 74 for (int i = 0; i < sc; ++i) { 75 segment &s = segs[a[i]]; 76 if (st & s.c) { 77 if (last != -1) 78 ans += (ll)sum[1] * (s.h - segs[last].h); 79 ql = s.lid, qr = s.rid, val = s.d; 80 modify(1, 1, xc - 1); 81 last = a[i]; 82 } 83 } 84 } 85 printf("Case %d:\n", Tc); 86 printf(lld, _[7] - _[6]); 87 printf(lld, _[7] - _[5]); 88 printf(lld, _[7] - _[3]); 89 printf(lld, _[5] - _[4] + _[6] - _[7]); 90 printf(lld, _[3] - _[2] + _[6] - _[7]); 91 printf(lld, _[3] - _[1] + _[5] - _[7]); 92 printf(lld, _[1] + _[2] - _[3] + _[4] - _[5] - _[6] + _[7]); 93 } 94 return 0; 95 }