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