HDU 4419 Colorful Rectangle 线段树 扫描线 矩形面积并 容斥原理

题目链接

感谢YB,CQ。

用线段树算出7种不同颜色的矩形面积并集,然后容斥原理分别算出每块单独颜色的面积。

这里的线段树写法比较特殊,只需要修改操作,查询的结果在1那个节点那里,重点是pushUp,因为这里扫描线求矩形面积并是一种特殊区间修改(保证随时都大于0,相同区间至少会有2个,一个下边,一个上边,所以可以不用像一般的区间修改线段树一样带Lazy标记的同时需要pushDown),标记当前区间是否存在,不存在就访问左右孩子。

 

 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 }
View Code

 

posted @ 2016-11-08 20:39  Apiec  阅读(286)  评论(0编辑  收藏  举报