HDU 4419 Colourful Rectangle (線段樹掃描線),hdu4419

來源:互聯網
上載者:User

HDU 4419 Colourful Rectangle (線段樹掃描線),hdu4419

http://acm.hdu.edu.cn/showproblem.php?pid=4419

Colourful RectangleTime Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1272    Accepted Submission(s): 504


Problem DescriptionWe use Red, Green and Blue to make new colours. See the picture below:


Now give you n rectangles, the colour of them is red or green or blue. You have calculate the area of 7 different colour. (Note: A region may be covered by same colour several times, but it’s final colour depends on the kinds of different colour) 
InputThe first line is an integer T(T <= 10), the number of test cases. The first line of each case contains a integer n (0 < n <= 10000), the number of rectangles. Then n lines follows. Each line start with a letter C(R means Red, G means Green, B means Blue) and four integers x1, y1, x2, y2(0 <= x1 < x2 < 10^9, 0 <= y1 < y2 < 10^9), the left-bottom's coordinate and the right-top's coordinate of a rectangle.
 
OutputFor each case, output a line "Case a:", a is the case number starting from 1,then 7 lines, each line contain a integer, the area of each colour. (Note: You should print the areas as the order: R, G, B, RG, RB, GB, RGB).
 
Sample Input
32R 0 0 2 2G 1 1 3 3 3R 0 0 4 4G 2 0 6 4B 0 2 6 63G 2 0 3 8G 1 0 6 1B 4 2 7 7
 
Sample Output
Case 1:3301000Case 2:44124444Case 3:012150000
 
Source2012 ACM/ICPC Asia Regional Hangzhou Online 

題意:

給出R,G,B三種顏色的矩形的資料,求最後7種顏色(R,G,B,RG,RB,GB,RGB)的面積是多少?

分析:

顯然的線段樹掃描線,可以說這題非常考驗對線段樹掃描線的理解,如果只會用模板,恐怕很難做出來。

R,G,B三種顏色最後會產生7種顏色(無色不算),可以預見本題對編碼品質要求相當之高。

update()操作和一般的線段樹掃描線並無太大的不同,本題的精髓在於query()!

一般的簡單掃描線甚至不用寫query,因為根結點維護的區間覆蓋長度就是我們所需要的。但是本題需要從複雜的資訊中分出7種資訊!顯然根結點不能直接拿來用。

什麼樣的資訊是我們需要的呢?如果我們能確定一個區間(結點)的顏色,那麼該區間(結點)的資訊就是我們所需要的,否則我們應繼續查詢他的左右兒子。那麼如何確定一個區間(結點)的顏色呢?顯然如果R,G,B三色要麼能覆蓋整個區間或不在這個區間(見我代碼中的judge()函數),那麼該區間的顏色就能確定!然後再計算該區間(結點)的有用資訊(_plus()函數)。

如果僅僅如此,依然只是套模板的水平。本題與一般的線段樹掃描線的不同之處在於查詢時需要向下傳遞資訊(pushdown()函數)!為什嗎?比如在[3,7)區間內,R覆蓋了[3,7)這一條,G覆蓋了[5,7)這一條,當我們查詢到[3,7)時,並不能確定該區間(結點)的顏色,所以我們就要查詢它的左右兒子。但如果直接查詢,可能會丟失一部分我們需要的資訊,比如[3,7)的R,如果不下傳,這條線段的資訊就會被丟失!當然,我們查詢過後需要恢複下傳的資訊(recover()函數),否則會出現資訊的重複,導致最終無法把線段刪除乾淨。


/* * *  Author  :  fcbruce * *  Date  :  2014-09-23 23:34:34  * */#include <cstdio>#include <iostream>#include <sstream>#include <cstdlib>#include <algorithm>#include <ctime>#include <cctype>#include <cmath>#include <string>#include <cstring>#include <stack>#include <queue>#include <list>#include <vector>#include <map>#include <set>#define sqr(x) ((x)*(x))#define LL long long#define itn int#define INF 0x3f3f3f3f#define PI 3.1415926535897932384626#define eps 1e-10#ifdef _WIN32  #define lld "%I64d"#else  #define lld "%lld"#endif#define maxm #define maxn 10007using namespace std;long long l_r,l_g,l_b,l_rg,l_rb,l_gb,l_rgb;struct __seg{  int l,r,h,type,col;  bool operator < (const __seg &s)const  {    return h<s.h;  }}seg[maxn<<1];int X[maxn<<1];int sum_r[maxn<<2],sum_g[maxn<<2],sum_b[maxn<<2];int col_r[maxn<<2],col_g[maxn<<2],col_b[maxn<<2];inline voidpushup(int k,int l,int r){  int lc=k*2+1,rc=k*2+2;    sum_r[k]=sum_g[k]=sum_b[k]=0;    if (r-l>1)  {    sum_r[k]=sum_r[lc]+sum_r[rc];    sum_g[k]=sum_g[lc]+sum_g[rc];    sum_b[k]=sum_b[lc]+sum_b[rc];  }    if (col_r[k]>0) sum_r[k]=X[r]-X[l];  if (col_g[k]>0) sum_g[k]=X[r]-X[l];  if (col_b[k]>0) sum_b[k]=X[r]-X[l];}voidupdate(int a,int b,int col,int v,int k,int l,int r){  if (b<=l || r<=a) return ;  if (a<=l && r<=b)  {    switch(col)    {      case 1:col_r[k]+=v;break;      case 2:col_g[k]+=v;break;      case 3:col_b[k]+=v;break;    }    pushup(k,l,r);    return ;  }    update(a,b,col,v,k*2+1,l,l+r>>1);  update(a,b,col,v,k*2+2,l+r>>1,r);    pushup(k,l,r);}inline booljudge(int k,int l,int r){  return (sum_r[k]==X[r]-X[l] || sum_r[k]==0) &&          (sum_g[k]==X[r]-X[l] || sum_g[k]==0) &&          (sum_b[k]==X[r]-X[l] || sum_b[k]==0);}inline void_plus(int k,int l,int r){  int type=0;  if (sum_r[k]==X[r]-X[l]) type|=1<<0;  if (sum_g[k]==X[r]-X[l]) type|=1<<1;  if (sum_b[k]==X[r]-X[l]) type|=1<<2;  switch (type)  {    case 0:      break;    case 1:      l_r+=X[r]-X[l];      break;    case 2:      l_g+=X[r]-X[l];      break;    case 3:      l_rg+=X[r]-X[l];      break;    case 4:      l_b+=X[r]-X[l];      break;    case 5:      l_rb+=X[r]-X[l];      break;    case 6:      l_gb+=X[r]-X[l];      break;    case 7:      l_rgb+=X[r]-X[l];      break;  }}inline voidpushdown(int k,int l,int r){  int lc=k*2+1,rc=k*2+2,m=l+r>>1;    col_r[lc]+=col_r[k];  col_r[rc]+=col_r[k];  col_g[lc]+=col_g[k];  col_g[rc]+=col_g[k];  col_b[lc]+=col_b[k];  col_b[rc]+=col_b[k];      pushup(lc,l,m);  pushup(rc,m,r);}inline voidrecover(int k,int l,int r){  int lc=k*2+1,rc=k*2+2,m=l+r>>1;    col_r[lc]-=col_r[k];  col_r[rc]-=col_r[k];  col_g[lc]-=col_g[k];  col_g[rc]-=col_g[k];  col_b[lc]-=col_b[k];  col_b[rc]-=col_b[k];    pushup(lc,l,m);  pushup(rc,m,r);}voidquery(int k,int l,int r){    if (judge(k,l,r))  {    _plus(k,l,r);    return ;  }    pushdown(k,l,r);    query(k*2+1,l,l+r>>1);  query(k*2+2,l+r>>1,r);    recover(k,l,r);}intmain(){#ifdef FCBRUCE  freopen("/home/fcbruce/code/t","r",stdin);#endif // FCBRUCE    int T_T,__=0;  scanf("%d",&T_T);    while (T_T--)  {    int n;    scanf("%d",&n);    char _col;    int x1,y1,x2,y2;    int cnt=0,xn=0,col;    for (int i=0;i<n;i++)    {      scanf(" %c%d%d%d%d",&_col,&x1,&y1,&x2,&y2);      switch (_col)      {        case 'R':          col=1;          break;        case 'G':          col=2;          break;        case 'B':          col=3;          break;      }      seg[cnt++]=(__seg){x1,x2,y1,1,col};      seg[cnt++]=(__seg){x1,x2,y2,-1,col};      X[xn++]=x1;      X[xn++]=x2;    }        sort(seg,seg+cnt);        sort(X,X+xn);    xn=unique(X,X+xn)-X;    xn--;        int last=0;    long long a_r,a_g,a_b,a_rg,a_rb,a_gb,a_rgb;    a_r=a_g=a_b=a_rg=a_rb=a_gb=a_rgb=0;        memset(sum_r,0,sizeof sum_r);    memset(sum_g,0,sizeof sum_g);    memset(sum_b,0,sizeof sum_b);    memset(col_r,0,sizeof col_r);    memset(col_g,0,sizeof col_g);    memset(col_b,0,sizeof col_b);        for (int i=0;i<cnt;i++)    {      int a=lower_bound(X,X+xn,seg[i].l)-X;      int b=lower_bound(X,X+xn,seg[i].r)-X;      int col=seg[i].col,v=seg[i].type;            l_r=l_g=l_b=l_rg=l_rb=l_gb=l_rgb=0;            query(0,0,xn);            a_r+=l_r*(seg[i].h-last);      a_g+=l_g*(seg[i].h-last);      a_b+=l_b*(seg[i].h-last);      a_rg+=l_rg*(seg[i].h-last);      a_rb+=l_rb*(seg[i].h-last);      a_gb+=l_gb*(seg[i].h-last);      a_rgb+=l_rgb*(seg[i].h-last);            last=seg[i].h;            update(a,b,col,v,0,0,xn);    }        printf("Case %d:\n",++__);        printf(lld "\n",a_r);    printf(lld "\n",a_g);    printf(lld "\n",a_b);    printf(lld "\n",a_rg);    printf(lld "\n",a_rb);    printf(lld "\n",a_gb);    printf(lld "\n",a_rgb);  }    return 0;}





聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.