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 }

 

你可能感兴趣的:(HDU)