【HDU1199】 离散化线段树

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1199

 

题目大意: 一段长度未知的线段,一种操作:a b c ,表示区间[a,b]要涂的颜色,c=w涂白色,c=b涂黑色,问你最长的白色区间段时多长。

 

解题思路:

            就快去南京邀请赛了,最近做题超没状态,CF rating一直掉,这么简单的线段树离散化居然搞了我一个晚上,纠结。

            开始用线段树区间合并的方法做,WA到死,换个写法,又WA到死,没处理好边界问题。

            这题用普通的离散化没用,藐视这种离散化第一次遇见,以前的离散化要么就是点化点,线段化点,这题不一样,是点化线段,一不小心处理不好就WA了。

点化线段我利用的是左闭右开,即对于一段区间[a,b],转化成区间[a,b+1),接下来就是把所有端点当做简单的离散化处理了,然后运用线段树成段更新操作处理就好了。

View Code
  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <algorithm>
  5 using namespace std;
  6 
  7 #define lz 2*u,l,mid
  8 #define rz 2*u+1,mid,r   ///注意:这里是点化为线段(左闭右开)
  9 const int maxn=5555;
 10 const int oo=0x3fffffff;
 11 int flag[4*maxn], color[maxn];
 12 int X[maxn];
 13 
 14 struct Node
 15 {
 16     int lx, rx, s;
 17     Node(){}
 18     Node(int lx_, int rx_, int s_)
 19     {
 20         lx=lx_, rx=rx_, s=s_;
 21     }
 22 }line[maxn];
 23 
 24 void push_down(int u, int l, int r)
 25 {
 26     if(flag[u]==-1) return ;
 27     else
 28     {
 29         flag[2*u]=flag[2*u+1]=flag[u];
 30         flag[u]=-1;
 31     }
 32 }
 33 
 34 void Update(int u, int l, int r, int tl, int tr, int c)
 35 {
 36     if(tl>=tr) return ; ///这里要注意了
 37     if(tl<=l&&r<=tr)
 38     {
 39         flag[u]=c;
 40         return ;
 41     }
 42     push_down(u,l,r);
 43     int mid=(l+r)>>1;
 44     if(tr<=mid) Update(lz,tl,tr,c);
 45     else if(tl>mid) Update(rz,tl,tr,c);
 46     else
 47     {
 48         Update(lz,tl,mid,c);
 49         Update(rz,mid,tr,c);
 50     }
 51 }
 52 
 53 void Query(int u, int l, int r)
 54 {
 55     if(l>=r) return ; ///!!!
 56     if(flag[u]!=-1)
 57     {
 58         for(int i=l; i<r; i++) color[i]=flag[u];  ///右端点不标记
 59         return ;
 60     }
 61     push_down(u,l,r);
 62     int mid=(l+r)>>1;
 63     Query(lz);
 64     Query(rz);
 65 }
 66 
 67 int find(int tmp, int n)
 68 {
 69     int l=1, r=n, mid;
 70     while(l<=r)
 71     {
 72         mid=(l+r)>>1;
 73         if(X[mid]==tmp) return mid;
 74         else if(X[mid]<tmp) l=mid+1;
 75         else r=mid-1;
 76     }
 77 }
 78 
 79 int main()
 80 {
 81     int n, x, y, c;
 82     char ch[3];
 83     while(~scanf("%d",&n))
 84     {
 85         int num=0;
 86         for(int i=0; i<n; i++)
 87         {
 88             scanf("%d%d%s",&x,&y,ch);
 89             if(*ch=='w') c=1;
 90             else c=0;
 91             line[i]=Node(x,y+1,c);
 92             X[++num]=x;
 93             X[++num]=y+1;
 94         }
 95         sort(X+1,X+num+1);
 96         int ep=1;
 97         for(int i=2; i<=num; i++)
 98             if(X[ep]!=X[i]) X[++ep]=X[i];
 99         memset(color,0,sizeof(color));
100         memset(flag,-1,sizeof(flag));
101         for(int i=0; i<n; i++)
102         {
103             int lx=find(line[i].lx,ep);
104             int rx=find(line[i].rx,ep);
105             Update(1,1,ep+1,lx,rx,line[i].s);
106         }
107         Query(1,1,ep+1);
108         int s=0, d=0, ts, td;
109         for(int i=1; i<=ep; i++)
110         {
111               if(color[i]!=1) continue;
112               ts=X[i];
113               while(color[i]==1) i++;
114               if(i>ep) break;
115               td=X[i];
116               if(td-ts>d-s)
117               {
118                   s=ts;
119                   d=td;
120               }
121         }
122         if(s==d) puts("Oh, my god");
123         else printf("%d %d\n",s, d-1);
124     }
125     return 0;
126 }

 

posted @ 2013-04-27 23:27  Mr. Ant  阅读(438)  评论(0编辑  收藏  举报