【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 }

 

你可能感兴趣的:(HDU)