BZOJ 1018 线段树维护连通性
这个题我总是想用循环完成转移,最后发现,还是手工枚举最靠谱~
建立线段树,线段树的每个节点(代表的是区间)维护以上六个值,true表示连通,false表示不连通,具体可以看我的代码~
View Code
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <algorithm> 6 7 #define N 111111 8 9 using namespace std; 10 11 struct DAT 12 { 13 bool v[2],s[2],x[2]; 14 void prt() {printf("s:%d %d\nx:%d %d\nv:%d %d\n\n",s[0],s[1],x[0],x[1],v[0],v[1]);} 15 }dat[N<<2]; 16 17 bool a[N][2][2]; 18 int n,r1,r2,c1,c2; 19 int dx[3]={-1,0,1}; 20 int dy[3]={0,1,0}; 21 22 inline void build(int u,int l,int r) 23 { 24 if(l==r) {dat[u].s[0]=dat[u].s[1]=true;return;} 25 int mid=(l+r)>>1; 26 build(u<<1,l,mid); build(u<<1|1,mid+1,r); 27 } 28 29 inline void pack(DAT &u,DAT &ls,DAT &rs,int mid) 30 { 31 u.x[0]=ls.x[0]||(ls.s[0]&&a[mid][0][0]&&rs.x[0]&&a[mid][1][0]&&ls.s[1]);//左上-右上 32 u.x[1]=rs.x[1]||(rs.s[0]&&a[mid][0][0]&&ls.x[1]&&a[mid][1][0]&&rs.s[1]);//左下-右下 33 u.s[0]=(ls.s[0]&&a[mid][0][0]&&rs.s[0])||(ls.v[0]&&a[mid][1][0]&&rs.v[1]);//左上-左下 34 u.s[1]=(ls.s[1]&&a[mid][1][0]&&rs.s[1])||(ls.v[1]&&a[mid][0][0]&&rs.v[0]);//右上-右下 35 u.v[0]=(ls.s[0]&&a[mid][0][0]&&rs.v[0])||(ls.v[0]&&a[mid][1][0]&&rs.s[1]);//左上-右下 36 u.v[1]=(ls.s[1]&&a[mid][1][0]&&rs.v[1])||(ls.v[1]&&a[mid][0][0]&&rs.s[0]);//右上-左下 37 } 38 39 inline void updata(int u,int l,int r,int p) 40 { 41 if(l==r) 42 { 43 dat[u].x[0]=dat[u].x[1]=dat[u].v[1]=dat[u].v[0]=a[p][0][1]; 44 dat[u].s[0]=dat[u].s[1]=true; 45 return; 46 } 47 int mid=(l+r)>>1; 48 if(p<=mid) updata(u<<1,l,mid,p); 49 else updata(u<<1|1,mid+1,r,p); 50 pack(dat[u],dat[u<<1],dat[u<<1|1],mid); 51 } 52 53 inline void change(bool pd) 54 { 55 if(r1>r2) swap(r1,r2),swap(c1,c2); 56 int dir; 57 for(int i=0;i<3;i++) 58 if(c1+dx[i]==c2&&r1+dy[i]==r2) dir=i; 59 if(dir==0) a[c2][r2][0]=pd,updata(1,1,n,c2); 60 else if(dir==1) a[c1][0][1]=pd,updata(1,1,n,c1); 61 else a[c1][r1][0]=pd,updata(1,1,n,c1); 62 } 63 64 inline void getpack(DAT &p,int u,int L,int R,int l,int r) 65 { 66 if(l<=L&&r>=R) {p=dat[u];return;} 67 int MID=(L+R)>>1; 68 if(r<=MID) getpack(p,u<<1,L,MID,l,r); 69 else if(l>=MID+1) getpack(p,u<<1|1,MID+1,R,l,r); 70 else 71 { 72 DAT tmp1,tmp2; 73 getpack(tmp1,u<<1,L,MID,l,MID); 74 getpack(tmp2,u<<1|1,MID+1,R,MID+1,r); 75 pack(p,tmp1,tmp2,MID); 76 } 77 } 78 79 inline void getans() 80 { 81 if(c1>c2) swap(c1,c2),swap(r1,r2); 82 DAT pa,pb,pc; 83 getpack(pa,1,1,n,1,c1); 84 getpack(pb,1,1,n,c1,c2); 85 getpack(pc,1,1,n,c2,n); 86 if(r1==r2) 87 { 88 if(r1==0) 89 { 90 if(pb.s[0]||(pa.x[1]&&pb.v[1])||(pc.x[0]&&pb.v[0])||(pa.x[1]&&pb.s[1]&&pc.x[0])) puts("Y"); 91 else puts("N"); 92 } 93 else 94 { 95 if(pb.s[1]||(pa.x[1]&&pb.v[0])||(pc.x[0]&&pb.v[1])||(pa.x[1]&&pb.s[0]&&pc.x[0])) puts("Y"); 96 else puts("N"); 97 } 98 } 99 else 100 { 101 if(r1==0) 102 { 103 if(pb.v[0]||(pa.x[1]&&pb.s[1])||(pc.x[0]&&pb.s[0])) puts("Y"); 104 else puts("N"); 105 } 106 else 107 { 108 if(pb.v[1]||(pa.x[1]&&pb.s[0])||(pc.x[0]&&pb.s[1])) puts("Y"); 109 else puts("N"); 110 } 111 } 112 } 113 114 inline void go() 115 { 116 char str[10]; 117 scanf("%d",&n); 118 build(1,1,n); 119 while(scanf("%s",str)) 120 { 121 if(str[0]=='E') break; 122 scanf("%d%d%d%d",&r1,&c1,&r2,&c2); 123 r1--; r2--; 124 if(str[0]=='O') change(1); 125 else if(str[0]=='C') change(0); 126 else getans(); 127 } 128 } 129 130 int main() 131 { 132 go(); 133 return 0; 134 }
感觉这个题还是挺神的~
没有人能阻止我前进的步伐,除了我自己!