BZOJ_1018_[SHOI2008]_交通堵塞traffic_(线段树)
描述
http://www.lydsy.com/JudgeOnline/problem.php?id=1018
\(2*n\)的距形,起初没有边相连,之后有三种操作:
1.加边.
2.删边.
3.询问某两个点是否联通.
分析
这题太神了...
用线段树维护连通性...
放弃解释清楚了...
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 const int maxn=1e5+5; 5 int n,cnt; 6 char s[10]; 7 bool A[maxn][2]; 8 struct node{ 9 bool a[2][2]; 10 node(){ 11 a[0][0]=a[0][1]=a[1][0]=a[1][1]=false; 12 } 13 bool* operator [] (int id){return a[id];} 14 }a[maxn<<4]; 15 struct Segment_tree{ 16 node merge(bool *a,node x,node y){ 17 node t; 18 t[0][0]=(x[0][0]&a[0]&y[0][0])|(x[0][1]&a[1]&y[1][0]); 19 t[0][1]=(x[0][0]&a[0]&y[0][1])|(x[0][1]&a[1]&y[1][1]); 20 t[1][0]=(x[1][0]&a[0]&y[0][0])|(x[1][1]&a[1]&y[1][0]); 21 t[1][1]=(x[1][1]&a[1]&y[1][1])|(x[1][0]&a[0]&y[0][1]); 22 return t; 23 } 24 void build_tree(int l,int r,int k){ 25 if(l==r){a[k][0][0]=a[k][1][1]=true;return;} 26 int mid=l+(r-l)/2; 27 build_tree(l,mid,k<<1); build_tree(mid+1,r,k<<1|1); 28 } 29 void update(int l,int r,int k,int pos,bool op,bool dir){ 30 if(l==r){ 31 if(dir) a[k][0][1]=a[k][1][0]=op;//c 32 return; 33 } 34 int mid=l+(r-l)/2; 35 if(!dir&&pos==mid){//r 36 a[k]=merge(A[mid],a[k<<1],a[k<<1|1]); 37 return; 38 } 39 if(pos<=mid) update(l,mid,k<<1,pos,op,dir); 40 else update(mid+1,r,k<<1|1,pos,op,dir); 41 a[k]=merge(A[mid],a[k<<1],a[k<<1|1]); 42 } 43 void _get_right(int l,int r,int k,int &pos,node &t,bool dir){ 44 if(l==r) return; 45 int mid=l+(r-l)/2; 46 node tmp=merge(A[l-1],t,a[k<<1]); 47 if(tmp[dir][0]||tmp[dir][1]) pos=mid, t=tmp, _get_right(mid+1,r,k<<1|1,pos,t,dir); 48 else _get_right(l,mid,k<<1,pos,t,dir); 49 } 50 void _get_left(int l,int r,int k,int &pos,node &t,bool dir){ 51 if(l==r) return; 52 int mid=l+(r-l)/2; 53 node tmp=merge(A[r],a[k<<1|1],t); 54 if(tmp[0][dir]||tmp[1][dir]) pos=mid+1,t=tmp, _get_left(l,mid,k<<1,pos,t,dir); 55 else _get_left(mid+1,r,k<<1|1,pos,t,dir); 56 } 57 void get_right(int l,int r,int k,int &pos,node &t,bool dir){ 58 if(l==r) {t=a[k];return;} 59 int mid=l+(r-l)/2; 60 if(pos>mid) get_right(mid+1,r,k<<1|1,pos,t,dir); 61 else{ 62 get_right(l,mid,k<<1,pos,t,dir); 63 if(pos!=mid) return; 64 node tmp=merge(A[mid],t,a[k<<1|1]); 65 if(tmp[dir][0]||tmp[dir][1]) pos=r,t=tmp; 66 else _get_right(mid+1,r,k<<1|1,pos,t,dir); 67 } 68 } 69 void get_left(int l,int r,int k,int &pos,node &t,bool dir){ 70 if(l==r) {t=a[k];return;} 71 int mid=l+(r-l)/2; 72 if(pos<=mid) get_left(l,mid,k<<1,pos,t,dir); 73 else{ 74 get_left(mid+1,r,k<<1|1,pos,t,dir); 75 if(pos!=mid+1) return; 76 node tmp=merge(A[mid],a[k<<1],t); 77 if(tmp[0][dir]||tmp[1][dir]) pos=l,t=tmp; 78 else _get_left(l,mid,k<<1,pos,t,dir); 79 } 80 } 81 node get_ans(int l,int r,int k,int x,int y){ 82 if(l==x&&r==y) return a[k]; 83 int mid=l+(r-l)/2; 84 if(y<=mid) return get_ans(l,mid,k<<1,x,y); 85 if(x>mid) return get_ans(mid+1,r,k<<1|1,x,y); 86 return merge(A[mid],get_ans(l,mid,k<<1,x,mid),get_ans(mid+1,r,k<<1|1,mid+1,y)); 87 } 88 }t; 89 void update(int x1,int y1,int x2,int y2,bool op){ 90 if(x1==x2){//r 91 if(y1>y2) swap(y1,y2); 92 A[y1][x1]=op; 93 t.update(1,n,1,y1,op,false); 94 } 95 else t.update(1,n,1,y1,op,true);//c 96 } 97 void query(int x1,int y1,int x2,int y2){ 98 if(y1>y2) swap(x1,x2), swap(y1,y2); 99 node tmp1; 100 t.get_left(1,n,1,y1,tmp1,x1); 101 x1=tmp1[0][x1]?0:1; 102 node tmp2; 103 t.get_right(1,n,1,y2,tmp2,x2); 104 x2=tmp2[x2][0]?0:1; 105 node tmp=t.get_ans(1,n,1,y1,y2); 106 puts(tmp[x1][x2]?"Y":"N"); 107 108 } 109 int main(){ 110 int x1,y1,x2,y2; 111 scanf("%d",&n); 112 t.build_tree(1,n,1); 113 while(true){ 114 scanf("%s",s); 115 if(s[0]=='C') scanf("%d%d%d%d",&x1,&y1,&x2,&y2), update(x1-1,y1,x2-1,y2,false); 116 else if(s[0]=='O') scanf("%d%d%d%d",&x1,&y1,&x2,&y2), update(x1-1,y1,x2-1,y2,true); 117 else if(s[0]=='A') scanf("%d%d%d%d",&x1,&y1,&x2,&y2), query(x1-1,y1,x2-1,y2); 118 else if(s[0]=='E') break; 119 } 120 return 0; 121 }
1018: [SHOI2008]堵塞的交通traffic
Time Limit: 3 Sec Memory Limit: 162 MBSubmit: 2747 Solved: 914
[Submit][Status][Discuss]
Description
有一天,由于某种穿越现象作用,你来到了传说中的小人国。小人国的布局非常奇特,整个国家的交通系统可
以被看成是一个2行C列的矩形网格,网格上的每个点代表一个城市,相邻的城市之间有一条道路,所以总共有2C个
城市和3C-2条道路。 小人国的交通状况非常槽糕。有的时候由于交通堵塞,两座城市之间的道路会变得不连通,
直到拥堵解决,道路才会恢复畅通。初来咋到的你决心毛遂自荐到交通部某份差事,部长听说你来自一个科技高度
发达的世界,喜出望外地要求你编写一个查询应答系统,以挽救已经病入膏肓的小人国交通系统。 小人国的交通
部将提供一些交通信息给你,你的任务是根据当前的交通情况回答查询的问题。交通信息可以分为以下几种格式:
Close r1 c1 r2 c2:相邻的两座城市(r1,c1)和(r2,c2)之间的道路被堵塞了;Open r1 c1 r2 c2:相邻的两座城
市(r1,c1)和(r2,c2)之间的道路被疏通了;Ask r1 c1 r2 c2:询问城市(r1,c1)和(r2,c2)是否连通。如果存在一
条路径使得这两条城市连通,则返回Y,否则返回N;
Input
第一行只有一个整数C,表示网格的列数。接下来若干行,每行为一条交通信息,以单独的一行“Exit”作为
结束。我们假设在一开始所有的道路都是堵塞的。我们保证 C小于等于100000,信息条数小于等于100000。
Output
对于每个查询,输出一个“Y”或“N”。
Sample Input
2
Open 1 1 1 2
Open 1 2 2 2
Ask 1 1 2 2
Ask 2 1 2 2
Exit
Open 1 1 1 2
Open 1 2 2 2
Ask 1 1 2 2
Ask 2 1 2 2
Exit
Sample Output
Y
N
N