BZOJ1018: [SHOI2008]堵塞的交通traffic
线段树维护每一块左上到左下、右上到右下、左上到右上、左下到右下、左上到右下、左下到右上的联通情况。
upd:可以直接用3082的方法搞,能过。
#include<bits/stdc++.h> #define N 100005 #define M (l+r>>1) #define P (k<<1) #define S (k<<1|1) #define K l,r,k #define L l,M,P #define R M+1,r,S #define Z \ int l=1,int r=n,int k=1 using namespace std; int n,m; struct node{ bool u[2],v[2],a[2]; }a[1<<18]; bool t[2][N]; node merge(node u,node v,Z){ node s[]={u,v},a; for(int i=0;i!=2;++i){ a.u[i]=s[0].u[i]&&t[i][M]&&s[1].u[i]||s[0].a[i]&&t[i^1][M]&&s[1].a[i^1]; a.v[i]=s[i].v[i]||t[0][M]&&s[i].u[0]&&s[i].u[1]&&t[1][M]&&s[i^1].v[i]; a.a[i]=s[0].u[i]&&t[i][M]&&s[1].a[i]||s[0].a[i]&&t[i^1][M]&&s[1].u[i^1]; } return a; } node query(int s,int t,Z){ return s==l&&t==r?a[k]:t<=M?query(s,t,L):s>M?query(s,t,R):merge(query(s,M,L),query(M+1,t,R),K); } bool solve(int s,int t,int i,int j){ node a=query(s,t); node u=query(1,s); node v=query(t,n); return i==j?u.v[1]&&a.u[i^1]&&v.v[0]||a.u[i]:a.u[j]&&u.v[1]||a.u[i]&&v.v[0]||a.a[i]||u.v[1]&&v.v[0]&&a.a[j]; } void build(Z){ if(l==r) memset(a[k].u,1,2); else{ build(L); build(R); } } void update(Z){ a[k]=merge(a[P],a[S],K); } void amend1(int t,Z){ if(l!=r){ if(t<=M) amend1(t,L); else amend1(t,R); update(K); } } void amend2(int s,int t,Z){ if(l==r){ memset(a[k].v,s,2); memset(a[k].a,s,2); }else{ if(t<=M) amend2(s,t,L); else amend2(s,t,R); update(K); } } int main(){ scanf("%d",&n); build(); char s[8]; while(scanf("%s",s),*s!='E'){ int u,v,i,j; scanf("%d%d%d%d",&i,&u,&j,&v); --i,--j; if(u>v){ swap(u,v); swap(i,j); } if(*s=='A') puts(solve(u,v,i,j)?"Y":"N"); else{ bool z=*s=='O'; if(i==j){ t[i][u]=z; amend1(u); }else amend2(z,u); } } }