hdu 4419 线段树 扫描线 离散化 矩形面积
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 }