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);
		}
	}
}
posted @ 2016-05-15 19:44  f321dd  阅读(166)  评论(0编辑  收藏  举报