hdu 1199 color the ball

离散化时将左右节点 (l[i],r[i]) 和左节点减1 (l[i]-1) 全部加入,离散化

建树时用段树方法比较方便,即叶子节点表示一个区间而不是一个值,很多边界问题就不用考虑了

1 #include<cstdio>
2 #include<cstring>
3 #include<algorithm>
4  using namespace std;
5  #define M 6060
6
7  int dis[M],m;
8 int Find(int x){
9 int low=0,high=m;
10 int mid=(low+high)>>1;
11 while(true){
12 if(dis[mid]==x){
13 return mid;
14 }else if(dis[mid]>x){
15 high=mid-1;
16 }else if(dis[mid]<x){
17 low=mid+1;
18 }
19 mid=(low+high)>>1;
20 }
21 }
22
23 struct Seg_Tree{
24 int left,right;
25 int lm,rm,len,lp;
26 bool col,flag;
27 //left,right 左右值(离散)
28 //lm,rm 表示该区间最左端和最右端的白色球区间的长度(非离散)
29 //len 表示该区间的最大长度(非离散)
30 //lp 表示该区间最大长度开始的位置(非离散)
31 //col 表示该区间是否为白色
32 //flag 传说中的lazy标记
33 int Glen(){
34 //该区间的总长度(非离散)
35 return dis[right]-dis[left];
36 }
37 }STree[M<<2];
38
39 void Build(int left,int right,int idx){
40 STree[idx].left=left;
41 STree[idx].right=right;
42 STree[idx].lm=0;
43 STree[idx].rm=0;
44 STree[idx].lp=dis[left];
45 STree[idx].len=0;
46 STree[idx].flag=false;
47 STree[idx].col=false;
48 //叶子节点是一个区间,处理长度时会方便很多
49 //注意下面递归时范围的不同
50 if(right-left==1) return;
51 int mid=(left+right)>>1;
52 Build(left,mid,idx<<1);
53 Build(mid,right,idx<<1|1);
54 }
55
56 void Update(int idx,bool val){
57 STree[idx].col=val;
58 STree[idx].flag=true;
59 if(val) STree[idx].len=STree[idx].Glen();
60 else STree[idx].len=0;
61 STree[idx].lm=STree[idx].rm=STree[idx].len;
62 STree[idx].lp=dis[STree[idx].left];
63 }
64
65 void Modify(int left,int right,int idx,bool val){
66 if(STree[idx].left==left&&STree[idx].right==right){
67 Update(idx,val);
68 return;
69 }
70
71 if(STree[idx].flag){
72 STree[idx].flag=false;
73 Update(idx<<1,STree[idx].col);
74 Update(idx<<1|1,STree[idx].col);
75 }
76
77 int mid=(STree[idx].left+STree[idx].right)>>1;
78 if(right<=mid){
79 Modify(left,right,idx<<1,val);
80 }else if(left>=mid){
81 Modify(left,right,idx<<1|1,val);
82 }else{
83 Modify(left,mid,idx<<1,val);
84 Modify(mid,right,idx<<1|1,val);
85 }
86
87 if(STree[idx<<1].len>=STree[idx<<1|1].len){
88 STree[idx].len=STree[idx<<1].len;
89 STree[idx].lp=STree[idx<<1].lp;
90 }else{
91 STree[idx].len=STree[idx<<1|1].len;
92 STree[idx].lp=STree[idx<<1|1].lp;
93 }
94 if(STree[idx<<1].rm+STree[idx<<1|1].lm>STree[idx].len){
95 STree[idx].len=STree[idx<<1].rm+STree[idx<<1|1].lm;
96 STree[idx].lp=dis[STree[idx<<1].right]-STree[idx<<1].rm;
97 }
98
99 STree[idx].lm=STree[idx<<1].lm;
100 if(STree[idx<<1].len==STree[idx<<1].Glen()){
101 STree[idx].lm=STree[idx<<1].len+STree[idx<<1|1].lm;
102 }
103 STree[idx].rm=STree[idx<<1|1].rm;
104 if(STree[idx<<1|1].len==STree[idx<<1|1].Glen()){
105 STree[idx].rm=STree[idx<<1|1].len+STree[idx<<1].rm;
106 }
107 }
108
109 int l[2010],r[2010];
110 bool c[2010];
111 int main(){
112 int n;
113 while(~scanf("%d",&n)){
114 for(int i=0;i<n;i++){
115 char col[5];
116 scanf("%d%d %s",&l[i],&r[i],col);
117 if(col[0]=='w'){
118 c[i]=true;
119 }else if(col[0]=='b'){
120 c[i]=false;
121 }
122 //l[i],r[i],l[i]-1 加入离散
123 //将l[i]-1改为r[i]+1也可,但要注意数据范围
124 dis[i*3]=l[i];
125 dis[i*3+1]=r[i];
126 dis[i*3+2]=l[i]-1;
127 }
128
129 sort(dis,dis+n*3);
130 m=0;
131 for(int i=1;i<n*3;i++){
132 if(dis[i]==dis[i-1]) continue;
133 dis[++m]=dis[i];
134 }
135
136 Build(0,m,1);
137 for(int i=0;i<n;i++){
138 //插入时将左值减1,全部转化为区间
139 int ll=Find(l[i])-1;
140 int rr=Find(r[i]);
141 Modify(ll,rr,1,c[i]);
142 }
143 if(STree[1].len==0){
144 puts("Oh, my god");
145 }else{
146 printf("%d %d\n",STree[1].lp+1,STree[1].lp+STree[1].len);
147 }
148 }
149 }
posted @ 2011-04-02 17:42  Amb@HDU  阅读(493)  评论(0编辑  收藏  举报