1 //离散化 + 扫描线 + 线段树
2 //这个线段树跟平常不太一样的地方在于记录了区间两个信息,len[i]表示颜色为i的被覆盖的长度为len[i], num[i]表示颜色i 『完全』覆盖了该区间几层。len[i]起传递儿子与父亲的关系,而num[i]不起传递作用,只是单纯的表示被覆盖的区间。
3 //然后就是pushUp函数,必须在update到底层后即更新num[]和len,然后把len传上去。
4 //离散化后由于求的是面积,所以我是把每条长度为1的线段当做一个点, 即把左端点表示此段长度。而不是把点当成点。
5 #include <iostream>
6 #include <cstdio>
7 #include <algorithm>
8 #include <cstring>
9 #include <cmath>
10
11 using namespace std;
12 #define lson l, m, rt<<1
13 #define rson m + 1, r, rt<<1|1
14 typedef long long ll;
15 const int maxn = 2e4 + 5;
16
17 struct Seg{
18 char c;
19 int y, s, t, tag;
20 }ss[maxn];
21 bool cmp(Seg a, Seg b){
22 return a.y < b.y;
23 }
24 int san[maxn], tot;
25 int num[maxn << 2][5],len[maxn << 2][8];
26 ll ans[8];
27 void pushUp(int l, int r, int rt){
28 int state = (num[rt][1] > 0 ? 1 : 0) | (num[rt][2] > 0 ? 2 : 0) | (num[rt][4] > 0 ? 4 : 0);
29 memset(len[rt], 0, sizeof(len[rt]));
30 if (state){
31 len[rt][state] = san[r] - san[l - 1];
32 for (int i = 1; i < 8; ++i){
33 if (state != (state|i)){
34 int tmp = len[rt<<1][i] + len[rt<<1|1][i];
35 len[rt][state|i] += tmp;
36 len[rt][state] -= tmp;
37 }
38 }
39 }
40 else if (l != r){
41 for (int i = 1; i < 8; ++i) len[rt][i] = len[rt<<1][i] + len[rt<<1|1][i];
42 }
43 }
44 int getC(char c){
45 if (c == 'R') return 1;
46 if (c == 'G') return 2;
47 return 4;
48 }
49 void update(int L, int R, char c, int tag, int l, int r, int rt){
50 if (L <= l && R >= r){
51 int cc = getC(c);
52 num[rt][cc] += tag;
53 //注意
54 pushUp(l, r, rt);
55 return ;
56 }
57 int m = (l + r) >> 1;
58 if (L <= m) update(L, R, c, tag, lson);
59 if (R > m) update(L, R, c, tag, rson);
60 pushUp(l, r, rt);
61 }
62 int T, n;
63 int main(){
64 int tcas = 0;
65 int x1, x2, y1, y2;
66 char s[3];
67 scanf("%d", &T);
68 while (T--){
69 scanf("%d", &n);
70 tot = 0;
71 for (int i = 1; i <= n; ++i){
72 scanf("%s%d%d%d%d", s,&x1, &y1, &x2, &y2);
73 ss[i].c = s[0]; ss[i].y = y1; ss[i].s = x1; ss[i].t = x2, ss[i].tag= 1;
74 ss[i + n].c = s[0]; ss[i + n].y = y2; ss[i + n].s = x1; ss[i + n].t = x2, ss[i + n].tag = -1;
75 san[tot++] = x1 ; san[tot++] = x2;
76 }
77 n = n * 2;
78
79 sort(san, san + tot);
80 tot = unique(san, san + tot) - san;
81 sort(ss + 1, ss + n + 1, cmp);
82 ss[0].y = ss[1].y;
83
84 memset(num, 0, sizeof(num));
85 memset(len, 0, sizeof(len));
86 memset(ans, 0, sizeof(ans));
87 for (int i = 1; i <= n; ++i){
88 int l = lower_bound(san, san + tot, ss[i].s) - san + 1;
89 int r = lower_bound(san, san + tot, ss[i].t) - san;
90 /*cout << " l = " << l << " r = " << r ;
91 cout << " tag = " << ss[i].tag << " c = "<< ss[i].c << endl;
92 for (int j = 1; j < 8; ++j) cout << len[1][j] << " ";
93 cout << endl;
94 cout << endl;
95 */
96 if (ss[i].y != ss[i - 1].y){
97 for (int j = 1; j < 8; ++j){
98 ans[j] += (ll)(ss[i].y - ss[i - 1].y) * (ll)len[1][j];
99 }
100 }
101 update(l, r, ss[i].c, ss[i].tag, 1, tot - 1, 1);
102 }
103 printf("Case %d:\n", ++tcas);
104 swap(ans[3], ans[4]);
105 for (int i = 1; i < 8; ++i)
106 printf("%lld\n", ans[i]);
107 }
108 return 0;
109 }