bzoj1018: [SHOI2008]堵塞的交通traffic
线段树维护联通性。
题目下方有分析。
题解里面说的行数等于题目中的行数-1.
经过分析一共(r1,c1)->(r2,c2)一共有四种方式。
假设r1=1,r2=0。
1.直接过去。
2.先到(0,c1)再过去。
3.先到(1,c2)再过去。
4.先到(0,c1)再到(1,c2)再过去。
用一个数组a1[i][j],维护从x节点最左端的i行能否到最右端的j行。
另一个数组a2[i],a2[0]表示x节点最右端的点能不能从右面绕到另外一行。a2[1]代表最左端的点能不能从左面绕到另外一行。
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int maxn = 800000 + 10; char s[20]; int x1,x2,y1,y2,c; struct Segtree { #define lc(x) ((x)<<1) #define rc(x) (((x)<<1)|1) #define root 1 struct Status { int a1[2][2],a2[2]; }s[maxn]; bool b[maxn][2]; int l[maxn],r[maxn],m[maxn]; Status update(Status s1,Status s2,bool b[]) { Status res; for(int i=0;i<=1;i++) for(int j=0;j<=1;j++) res.a1[i][j]=s1.a1[i][0] && b[0] && s2.a1[0][j] || s1.a1[i][1] && b[1] && s2.a1[1][j]; res.a2[0]=s1.a2[0] || s1.a1[0][0] && b[0] && s2.a2[0] && b[1] && s1.a1[1][1]; res.a2[1]=s2.a2[1] || s2.a1[0][0] && b[0] && s1.a2[1] && b[1] && s2.a1[1][1]; return res; } Status access (int x,int y1,int y2) { if(y1<=l[x] && r[x]<=y2) return s[x]; else if(y2<=m[x]) return access(lc(x),y1,y2); else if(y1>m[x]) return access(rc(x),y1,y2); else return update(access(lc(x),y1,y2),access(rc(x),y1,y2),b[x]); } void change(bool k,int x,int x1,int y1,int x2,int y2) { if(x1==x2 && y1==m[x]) { b[x][x1]=k; s[x]=update(s[lc(x)],s[rc(x)],b[x]); } else if(l[x]==r[x]) s[x].a1[0][1]=s[x].a1[1][0]=s[x].a2[0]=s[x].a2[1]=k; else { change(k,y2<=m[x]?lc(x):rc(x),x1,y1,x2,y2); s[x]=update(s[lc(x)],s[rc(x)],b[x]); } } void ask(int x1,int y1,int x2,int y2) { Status left=access(root,1,y1), right=access(root,y2,c), mid=access(root,y1,y2); bool res=false; for(int i=0;i<=1;i++) for(int j=0;j<=1;j++) if(mid.a1[i][j]&&(i==x1||left.a2[1])&&(j==x2||right.a2[0])) { res=true; break; } printf(res?"Y\n":"N\n"); } void build(int x,int y1,int y2) { l[x]=y1,r[x]=y2,m[x]=(l[x]+r[x])>>1; if(y1==y2) s[x].a1[0][0]=s[x].a1[1][1]=true; else { build(lc(x),y1,m[x]); build(rc(x),m[x]+1,y2); } } }seg; int main() { scanf("%d",&c); seg.build(1,1,c); while(1) { scanf("%s",s); if(s[0]=='E') break; scanf("%d%d%d%d",&x1,&y1,&x2,&y2); --x1; --x2; if(y1>y2) { swap(x1,x2); swap(y1,y2); } if(s[0]=='O') seg.change(1,1,x1,y1,x2,y2); else if(s[0]=='C') seg.change(0,1,x1,y1,x2,y2); else seg.ask(x1,y1,x2,y2); } return 0; }