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 }
相關文章
相關標籤/搜索