bzoj1018[SHOI2008]堵塞的交通traffic——线段树
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1018
巧妙的线段树。维护矩阵四个角的连通性。
考虑两个点连通的可能路径分成3部分:两点左边、两点中间、两点右边;
就拿中间部分来说,需要这个矩阵的四个角的连通性。所以就用线段树维护一下。
注意不要写得冗余了。比如同一块的左上到右下已经考虑过自己的左上到左下+左下到右下,更新别的块的时候不用再讨论第二种情况了。
还要注意不要搞混 r 和 c 。
(结构体真好用……)(u:lu-ru d:ld-rd U:mu D:md p:ld-ru q:lu-rd l:lu-ld r:ru-rd)
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int N=1e5+5; int n,tot=1,r1,c1,r2,c2; bool b[N<<1][10];//1:lu-ru 2:ld-rd 3:lu-rd 4:ld-ru 5:lu-ld 6:ru-rd 7:mu-mu 8:md-md struct Node{ int ls,rs; }a[N<<1]; struct Lt{bool l,r,u,d,U,D,p,q;}w[N<<1]; void build(int l,int r,int cr) { if(l==r) { // b[cr][1]=1;b[cr][2]=1; w[cr].u=w[cr].d=w[cr].U=w[cr].D=1; return; } int mid=((l+r)>>1); a[cr].ls=++tot;build(l,mid,tot); a[cr].rs=++tot;build(mid+1,r,tot); } //void pushup(int cr) //{ // int ls=a[cr].ls,rs=a[cr].rs; // if(b[ls][5]||(b[ls][1]&&b[cr][7]&&b[rs][5]&&b[cr][8]&&b[ls][2]))b[cr][5]=1;else b[cr][5]=0; // if(b[rs][6]||(b[rs][1]&&b[cr][7]&&b[ls][6]&&b[cr][8]&&b[rs][2]))b[cr][6]=1;else b[cr][6]=0; // if(b[cr][7]) // { // if((b[ls][1]||(b[ls][5]&&b[ls][4]))&&(b[rs][1]||(b[rs][3]&&b[rs][6])))b[cr][1]=1;else b[cr][1]=0; // if((b[ls][4]||(b[ls][5]&&b[ls][1]))&&(b[rs][3]||(b[rs][1]&&b[rs][6])))b[cr][2]=1;else b[cr][2]=0; // if(b[ls][1]&&b[rs][3])b[cr][3]=1;else b[cr][3]=0; // if(b[ls][4]&&b[rs][1])b[cr][4]=1;else b[cr][4]=0; // } // if(b[cr][8]) // { // if((b[ls][2]||(b[ls][5]&&b[ls][3]))&&(b[rs][2]||(b[rs][4]&&b[rs][6])))b[cr][2]=1; // if((b[ls][3]||(b[ls][5]&&b[ls][2]))&&(b[rs][4]||(b[rs][2]&&b[rs][4])))b[cr][1]=1; // if(b[ls][2]&&b[rs][4])b[cr][4]=1;if(b[ls][3]&&b[rs][2])b[cr][3]=1; // } //} void pushup(Lt &k,Lt x,Lt y)// &!!!!! { k.l=x.l|(x.u & k.U & y.l & k.D & x.d); k.r=y.r|(y.u & k.U & x.r & k.D & y.d); k.u=(x.u & k.U & y.u)|(x.q & k.D & y.p); k.d=(x.d & k.D & y.d)|(x.p & k.U & y.q); k.p=(x.d & k.D & y.p)|(x.p & k.U & y.u); k.q=(x.u & k.U & y.q)|(x.q & k.D & y.d); } //void mdfy(int l,int r,int cr,bool p) //{ // if(l>=r1&&r<=r2) // { // if(c1!=c2){b[cr][3]=p;b[cr][4]=p;b[cr][5]=p;b[cr][6]=p;} // else if(c1==1){ // b[cr][1]=p;b[cr][7]=p; // if(b[a[cr].ls][5])b[cr][4]=1;if(b[a[cr].rs][5])b[cr][3]=1; // } // else { // b[cr][2]=p;b[cr][8]=p; // if(b[a[cr].ls][5])b[cr][3]=1;if(b[a[cr].rs][5])b[cr][4]=1; // } // return; // } // int mid=l+r>>1; // if(mid>=r2)mdfy(l,mid,a[cr].ls,p); // else if(mid<r1)mdfy(mid+1,r,a[cr].rs,p); // else b[cr][c1==1?7:8]=1; // pushup(cr,a[cr].ls,a[cr].rs); //} void mdfyr(int l,int r,int cr,bool f) { int mid=((l+r)>>1); if(mid==c1) { if(r1==1)w[cr].U=f;else w[cr].D=f; pushup(w[cr],w[a[cr].ls],w[a[cr].rs]);return;//pushup } if(c1<mid)mdfyr(l,mid,a[cr].ls,f); else mdfyr(mid+1,r,a[cr].rs,f); pushup(w[cr],w[a[cr].ls],w[a[cr].rs]); } void mdfyc(int l,int r,int cr,bool f) { if(l==r) { w[cr].l=w[cr].r=w[cr].p=w[cr].q=f;return; } int mid=((l+r)>>1); if(mid>=c1)mdfyc(l,mid,a[cr].ls,f); else mdfyc(mid+1,r,a[cr].rs,f); pushup(w[cr],w[a[cr].ls],w[a[cr].rs]); } //bool query(int l,int r,int cr,int r1,int c1,int r2,int c2) //{ // if(l==r1&&r==r2) // { // if(c1==1&&c2==1)return b[cr][1]; // if(c1==1&&c2==2)return b[cr][3]; // if(c1==2&&c2==1)return b[cr][4]; // if(c1==2&&c2==2)return b[cr][2]; // } // int mid=l+r>>1,ls=a[cr].ls,rs=a[cr].rs; // if(mid>=r2)return query(l,mid,ls,r1,c1,r2,c2); // else if(mid<r1)return query(mid+1,r,rs,r1,c1,r2,c2); // else return ((b[cr][7]&&query(l,mid,ls,r1,c1,mid,1)&&query(mid+1,r,rs,mid,1,r2,c2)) // ||(b[cr][8]&&query(l,mid,ls,r1,c1,mid,2)&&query(mid+1,r,rs,mid,2,r2,c2))); //} //bool query(int l,int r,int cr,int r1,int c1,int r2,int c2) //{ //// printf("l=%d r=%d r1=%d c1=%d r2=%d c2=%d\n",l,r,r1,c1,r2,c2); // if(l==c1&&r==c2) // { // if(r1==r2){if(r1==1)return w[cr].u;else return w[cr].d;} // else {if(r1==1)return w[cr].q;else return w[cr].p;} // } // int mid=l+r>>1,ls=a[cr].ls,rs=a[cr].rs; // if(mid>=c2)return query(l,mid,ls,r1,c1,r2,c2); // else if(mid<c1)return query(mid+1,r,rs,r1,c1,r2,c2); // else return (w[cr].U&query(l,mid,ls,r1,c1,mid,1)&query(mid+1,r,rs,mid+1,1,r2,c2)) // |(w[cr].D&query(l,mid,ls,r1,c1,mid,2)&query(mid+1,r,rs,mid+1,2,r2,c2)); //} Lt query(int l,int r,int cr,int L,int R) { if(l>=L&&r<=R)return w[cr]; int mid=((l+r)>>1),ls=a[cr].ls,rs=a[cr].rs; if(mid>=R)return query(l,mid,ls,L,R); else if(mid<L)return query(mid+1,r,rs,L,R); else{ Lt ret=w[cr]; pushup(ret,query(l,mid,ls,L,R),query(mid+1,r,rs,L,R)); return ret; } } int main() { scanf("%d",&n);char ch[10]; build(1,n,1); while(1) { scanf("%s",ch);if(ch[0]=='E')return 0; scanf("%d%d%d%d",&r1,&c1,&r2,&c2); if(c1>c2)swap(r1,r2),swap(c1,c2); if(ch[0]=='O'||ch[0]=='C') { if(r1==r2)mdfyr(1,n,1,ch[0]=='O'?1:0); else mdfyc(1,n,1,ch[0]=='O'?1:0); } if(ch[0]=='A') { // if(query(1,n,1,r1,c1,r2,c2))printf("Y\n");else printf("N\n"); bool flag=0; Lt x=query(1,n,1,1,c1),y=query(1,n,1,c1,c2),z=query(1,n,1,c2,n); if(r1==1&&r2==1)flag=y.u|(x.r & y.d & z.l)|(y.q & z.l)|(x.r & y.p); if(r2==2&&r2==2)flag=y.d|(x.r & y.u & z.l)|(x.r & y.q)|(y.p & z.l); if(r1==1&&r2==2)flag=y.q|(x.r & y.p & z.l)|(x.r & y.d)|(y.u & z.l); if(r1==2&&r2==1)flag=y.p|(x.r & y.q & z.l)|(x.r & y.u)|(y.d & z.l); if(flag)printf("Y\n");else printf("N\n"); } } }