BZOJ 1018 [SHOI2008]堵塞的交通traffic

AC通道:http://www.lydsy.com/JudgeOnline/problem.php?id=1018

 

分析:

  为什么会只有2行呢?...于是我们就想到了:因为如果一行太水了[并查集真的可以弄么?...],如果多行好像又没那么好打了是吧...

  于是想到两行也可以当做一行来玩的吧...和序列有关的,想办法来维护连通性的数据结构...

  于是用到的是线段树咯:

   [下图是一个2*len的区间,其中四个角分别是lu,ru,ld,rd,方便和程序里面的变量对应]

  

  这是一个区间,我们需要维护的是四个角相互之间的联通情况,一共有六种:

    luru,lurd,ldru,ldrd,luld,rurd

  

  为什么要维护这个呢?

  因为如果我们这样维护了,那么其实也就知道了所有点之间的连通情况了...

  

  比如(x1,y1)与(x2,y2)一共有四种情况:

  

  然后对于每一种情况,都可以用上面的那些连通性来表示。

  比如我举一个第一种情况的例子,其它的情况类似:

  

  其中L表示[1,x1]的线段,M表示[x1,x2]的线段,R表示[x2,n]的线段,至于为什么需要L,R,图中也给的比较清楚了...[因为可能可以不走中间,而是从旁边绕一段来相连]

  为什么画的都是曲线呢?...因为笔者想表示出这两个点之间的连接情况其实是很复杂的...只能知道它们俩是连通的而已...[所以就有一点丑了...]

 

  然后我们知道了这样子维护一定可以求出任意两个点的连通情况,那么线段树还需要合并与修改,怎么办呢?...

  那我就只举一个luru的合并过程,其它的就可以举一反三了...

  

  当然还有我们的边界条件?...也就是线段长度为1的时候,自然有:

    luru=ldru=1;

    luld=lurd=ldru=rurd=list[i];

  其中list[i]表示第i个位置向下的连边。

 

  所以修改的时候,也只需要改一下list[],up[],down[],然后更新一下一个或两个被影响的点就可以了...

  代码很整齐很好看啊...很有逻辑很炫酷啊...不过有180行?...

  码力提升+++

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4  
  5 using namespace std;
  6  
  7 inline int in(){
  8     int x=0;char ch=getchar();
  9     while(ch>'9' || ch<'0') ch=getchar();
 10     while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
 11     return x;
 12 }
 13  
 14 const int maxn=100010;
 15 const int max_tree=maxn*5;
 16  
 17 struct Node{
 18     bool luru,lurd,ldru,ldrd,luld,rurd;
 19     // lu=left_up,ru=right_up,ld=left_down,rd=right_down;
 20 }s[max_tree];
 21  
 22 struct Ans{
 23     bool a,b,c,d,e,f;
 24 }False;
 25  
 26 int n,x1,y1,x2,y2;
 27 int num[max_tree];//标记每个节点所代表线段的右端点
 28 bool up[maxn],down[maxn],list[maxn];
 29 //up[i]表示上一行中i往右是否有连边,down[i]表示下一行,list表示上下两行之间
 30  
 31 inline void update(int o){
 32     bool a,b;
 33      
 34     a=s[o<<1].luru && s[o<<1|1].luru && up[num[o<<1]];
 35     b=s[o<<1].lurd && s[o<<1|1].ldru && down[num[o<<1]];
 36     s[o].luru=a|b;
 37      
 38     a=s[o<<1].luru && s[o<<1|1].lurd && up[num[o<<1]];
 39     b=s[o<<1].lurd && s[o<<1|1].ldrd && down[num[o<<1]];
 40     s[o].lurd=a|b;
 41      
 42     a=s[o<<1].ldru && s[o<<1|1].luru && up[num[o<<1]];
 43     b=s[o<<1].ldrd && s[o<<1|1].ldru && down[num[o<<1]];
 44     s[o].ldru=a|b;
 45      
 46     a=s[o<<1].ldru && s[o<<1|1].lurd && up[num[o<<1]];
 47     b=s[o<<1].ldrd && s[o<<1|1].ldrd && down[num[o<<1]];
 48     s[o].ldrd=a|b;
 49      
 50     a=s[o<<1].luld;
 51     b=s[o<<1].luru && s[o<<1].ldrd && s[o<<1|1].luld && up[num[o<<1]] && down[num[o<<1]];
 52     s[o].luld=a|b;
 53      
 54     a=s[o<<1|1].rurd;
 55     b=s[o<<1|1].luru && s[o<<1|1].ldrd && s[o<<1].rurd && up[num[o<<1]] && down[num[o<<1]];
 56     s[o].rurd=a|b;
 57 }
 58  
 59 void Build(int o,int l,int r){
 60     num[o]=r;
 61     if(l==r){s[o].luru=s[o].ldrd=true;return ;}
 62     int mid=(l+r)>>1;
 63     Build(o<<1,l,mid),Build(o<<1|1,mid+1,r);
 64     update(o);
 65 }
 66  
 67 void Modify(int o,int l,int r,int x){
 68     if(l==r){
 69         s[o].luru=s[o].ldrd=true;
 70         s[o].luld=s[o].lurd=s[o].ldru=s[o].rurd=list[l];
 71         return ;
 72     }
 73     int mid=(l+r)>>1;
 74     if(x<=mid) Modify(o<<1,l,mid,x);
 75     else Modify(o<<1|1,mid+1,r,x);
 76     update(o);
 77 }
 78  
 79 inline void Change(bool op){
 80     if(x1==x2)
 81         list[x1]=op,Modify(1,1,n,x1);
 82     else{
 83         if(!y1){
 84             up[x1]=op;
 85             Modify(1,1,n,x1);
 86             Modify(1,1,n,x2);
 87         }
 88         else{
 89             down[x1]=op;
 90             Modify(1,1,n,x1);
 91             Modify(1,1,n,x2);
 92         }
 93     }
 94 }
 95  
 96 Ans Query(int o,int l,int r,int al,int ar){
 97      
 98     if(al<=l && ar>=r)
 99         return (Ans){s[o].luru,s[o].ldrd,s[o].lurd,s[o].ldru,s[o].luld,s[o].rurd};
100      
101     int mid=(l+r)>>1;
102     bool pdl=0,pdr=0;
103     Ans L,R;
104      
105     if(al<=mid)
106         pdl=true,L=Query(o<<1,l,mid,al,ar);
107     if(ar>mid)
108         pdr=true,R=Query(o<<1|1,mid+1,r,al,ar);
109          
110     if(pdl && pdr){
111         bool a,b,c,d,e,f;
112          
113         a=(L.a && R.a && up[num[o<<1]]) || (L.c && R.d && down[num[o<<1]]);
114         b=(L.d && R.c && up[num[o<<1]]) || (L.b && R.b && down[num[o<<1]]);
115         c=(L.a && R.c && up[num[o<<1]]) || (L.c && R.b && down[num[o<<1]]);
116         d=(L.d && R.a && up[num[o<<1]]) || (L.b && R.d && down[num[o<<1]]);
117         e=(L.e) || (L.a && L.b && R.e && up[num[o<<1]] && down[num[o<<1]]);
118         f=(R.f) || (R.a && R.b && L.f && up[num[o<<1]] && down[num[o<<1]]);
119          
120         return (Ans){a,b,c,d,e,f};
121     }
122     else if(pdl) return L;
123     else if(pdr) return R;
124     else return False;
125 }
126  
127 inline bool ask(){
128     Ans l,r,m;
129      
130     m=Query(1,1,n,x1,x2);
131     l=Query(1,1,n,1,x1);
132     r=Query(1,1,n,x2,n);
133      
134     if(!y1 && !y2)
135         return m.a || (l.f && m.d) || (m.c && r.e) || (l.f && m.b && r.e);
136     if( y1 &&  y2)
137         return m.b || (l.f && m.c) || (m.d && r.e) || (l.f && m.a && r.e);
138     if(!y1 &&  y2)
139         return m.c || (l.f && m.b) || (m.a && r.e) || (l.f && m.d && r.e);
140     if( y1 && !y2)
141         return m.d || (l.f && m.a) || (m.b && r.e) || (l.f && m.c && r.e);
142 }
143  
144 int main(){
145 #ifndef ONLINE_JUDGE
146     freopen("1018.in","r",stdin);
147     freopen("1018.out","w",stdout);
148 #endif
149  
150     char ord[6];
151  
152     scanf("%d",&n);
153     Build(1,1,n);
154     while(~scanf("%s",ord)){
155         if(ord[0]=='E') return 0;
156          
157         y1=in(),x1=in(),y2=in(),x2=in();y1--,y2--;
158          
159         if(x1>x2){swap(x1,x2);swap(y1,y2);}
160          
161         if(ord[0]=='O') Change(1);
162         else if(ord[0]=='C') Change(0);
163         else{
164             if(ask()) puts("Y");
165             else puts("N");
166         }
167     }
168      
169     return 0;
170 }
View Code

 

 

posted @ 2016-03-29 19:26  诚叙  阅读(313)  评论(1编辑  收藏  举报