【BZOJ】【1018】【SHOI2008】堵塞的交通traffic
线段树
这题的线段树+分类讨论蛮神奇的……我以前学的线段树简直就是渣渣QAQ
看了下ydc题解里的思想>_>用线段树维护连通性!那么就自己写吧……每个节点表示一段区间的连通性(我的叶子节点表示的是一个方块型的四个点之间的连通性,所以我直接n--了)对线段树上每个节点维护6个信息,即四个端点中任意一对点之间的连通性。
维护连通性的时候要进行信息的整合,也就是说间接连通的要全部找到并标记上连通,举个例子:如果左边连通且下边两端点连通,则左上到右下连通。这是一个简单的讨论我就不细说了,自己想一下真的很容易<_<。
但是这时候我遇到了一个蛋疼的问题:对于叶子节点来说,如果我上下左右四条边都连着,那么肯定是完全连通的……但是如果这时候我删一条边(Close)该怎么办?因为连通性并没有任何变化,但是图跟原来不一样了……所以我选择单独开一个a数组存叶子的直接连通情况(也就是存原图)然后用线段树t维护直接间接连通。
好的这个时候这个线段树我们就维护好了,那么查询的时候就方便啦~我们可以查询一下L=[1,c1-1]这个区间的右端点是否连通
(保证了这种情况:)
查询一下R=[c2,n]这个区间左端点是否连通,跟上图类似,是在右边连通的
最后再查询一下mid=[c1,c2-1]这个区间的连通情况,如果L的右端点连通,则mid的左端点是连通的,mid的右端点同理(R的左端点)
然后重新维护下mid的连通情况……OK啦~
这题写的好辛苦……分类讨论总是想不清……
最后给个样例图吧~(红色的为查询点)
1 /************************************************************** 2 Problem: 1018 3 User: Tunix 4 Language: C++ 5 Result: Accepted 6 Time:1068 ms 7 Memory:4208 kb 8 ****************************************************************/ 9 10 //BZOJ 1018 11 #include<vector> 12 #include<cstdio> 13 #include<cstring> 14 #include<cstdlib> 15 #include<iostream> 16 #include<algorithm> 17 #define rep(i,n) for(int i=0;i<n;++i) 18 #define F(i,j,n) for(int i=j;i<=n;++i) 19 #define D(i,j,n) for(int i=j;i>=n;--i) 20 #define pb push_back 21 using namespace std; 22 inline int getint(){ 23 int v=0,sign=1; char ch=getchar(); 24 while(ch<'0'||ch>'9'){ if (ch=='-') sign=-1; ch=getchar();} 25 while(ch>='0'&&ch<='9'){ v=v*10+ch-'0'; ch=getchar();} 26 return v*sign; 27 } 28 const int N=1e5+10,INF=~0u>>2; 29 typedef long long LL; 30 /******************tamplate*********************/ 31 int n; 32 struct node{ 33 bool z,y,s,x,zs,zx; 34 node(bool z=0,bool y=0,bool s=0,bool x=0,bool zs=0,bool zx=0): 35 z(z),y(y),s(s),x(x),zs(zs),zx(zx){} 36 //z 左端两结点是否连通 37 //y 右端 38 //s 上方 39 //x 下方 40 //zs 左上->右下 41 //zx 左下->右上 42 }a[N],t[N<<2],ans; 43 #define L (o<<1) 44 #define R (o<<1|1) 45 #define mid (l+r>>1) 46 void maintain(node &a){ 47 a.zs|=(a.z&a.x) | (a.s&a.y); 48 a.zx|=(a.z&a.s) | (a.x&a.y); 49 a.z|=(a.zs&a.x) | (a.zx&a.s); 50 a.y|=(a.zs&a.s) | (a.zx&a.x); 51 a.s|=(a.zs&a.y) | (a.zx&a.z); 52 a.x|=(a.zs&a.z) | (a.zx&a.y); 53 } 54 node Union(node x,node y){ 55 node tmp; 56 tmp.z =x.z; tmp.y=y.y; 57 tmp.s =(x.s&y.s) | (x.zs&y.zx) ; 58 tmp.x =(x.x&y.x) | (x.zx&y.zs) ; 59 tmp.zs=(x.s&y.zs) | (x.zs&y.x) ; 60 tmp.zx=(x.x&y.zx) | (x.zx&y.s) ; 61 return tmp; 62 } 63 void update(int o,int l,int r,int pos,int num,bool v){ 64 //将pos位置的num号连通情况改为v 65 if (l==r){ 66 if (num==1) a[l].z=v; if (num==2) a[l].y=v; 67 if (num==3) a[l].s=v; if (num==4) a[l].x=v; 68 t[o]=a[l]; 69 }else{ 70 if (pos<=mid) update(L,l,mid,pos,num,v); 71 else update(R,mid+1,r,pos,num,v); 72 t[o]=Union(t[L],t[R]); 73 } 74 maintain(t[o]); 75 } 76 int ql,qr;bool sign=0; 77 void query(int o,int l,int r){ 78 if (ql<=l && qr>=r){ 79 if (!sign) {ans=t[o];sign=1;} 80 else ans=Union(ans,t[o]); 81 } 82 else{ 83 if (ql<=mid) query(L,l,mid); 84 if (qr>mid) query(R,mid+1,r); 85 } 86 } 87 int main(){ 88 #ifndef ONLINE_JUDGE 89 freopen("1018.in","r",stdin); 90 freopen("1018.out","w",stdout); 91 #endif 92 n=getint()-1; 93 int r1,r2,c1,c2; 94 char cmd[10]; 95 while(scanf("%s",cmd)!=EOF && cmd[0]!='E'){ 96 r1=getint(); c1=getint(); r2=getint(); c2=getint(); 97 if (c1>c2){swap(c1,c2); swap(r1,r2);} 98 if (cmd[0]=='A'){ 99 ans=node(); 100 if (c1==c2){ 101 if (c1<n+1 && c1>1){//不是右端点 102 node t1,t2; 103 ql=1; qr=c1-1; sign=0; 104 query(1,1,n); t1=ans; 105 ql=c1; qr=n; sign=0; 106 query(1,1,n); 107 ans.z|=t1.y; ans.z|=t2.z; 108 puts(ans.z?"Y":"N"); 109 }else if(c1==n+1){ 110 ans=t[1]; 111 puts(ans.y?"Y":"N"); 112 }else{ 113 ans=t[1]; 114 puts(ans.z?"Y":"N"); 115 } 116 }else{ 117 node t1,t2; 118 if (c1!=1){ql=1; qr=c1-1; sign=0; query(1,1,n); t1=ans;} 119 if (c2!=n+1){ql=c2; qr=n; sign=0; query(1,1,n); t2=ans;} 120 ql=c1; qr=c2-1; sign=0; 121 query(1,1,n); 122 ans.z|=t1.y | (t1.s & t1.z & t1.x); 123 ans.y|=t2.z | (t2.s & t2.y & t2.x); 124 maintain(ans); 125 if (r1==1 && r2==1) puts(ans.s ?"Y":"N"); 126 if (r1==2 && r2==2) puts(ans.x ?"Y":"N"); 127 if (r1==1 && r2==2) puts(ans.zs?"Y":"N"); 128 if (r1==2 && r2==1) puts(ans.zx?"Y":"N"); 129 } 130 }else{ 131 bool type=0; 132 if (cmd[0]=='O') type=1; 133 else type=0; 134 if (r1==r2){ 135 if (r1==1) update(1,1,n,c1,3,type); 136 else update(1,1,n,c1,4,type); 137 }else{ 138 if (c1<n+1) update(1,1,n,c1,1,type); 139 if (c1>1 ) update(1,1,n,c1-1,2,type); 140 } 141 } 142 } 143 return 0; 144 } 145
1018: [SHOI2008]堵塞的交通traffic
Time Limit: 3 Sec Memory Limit: 162 MBSubmit: 2030 Solved: 638
[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”作为结束。我们假设在一开始所有的道路都是堵塞的。 对30%测试数据,我们保证C小于等于1000,信息条数小于等于1000; 对100%测试数据,我们保证 C小于等于100000,信息条数小于等于100000。
Output
对于每个查询,输出一个“Y”或“N”。
Sample Input
Open 1 1 1 2
Open 1 2 2 2
Ask 1 1 2 2
Ask 2 1 2 2
Exit
Sample Output
N