【BZOJ】【P1018】【SHOI2008】【堵塞的交通traffic】【题解】【线段树】

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1018

分类讨论到吐,代码已经不能看了

明天就是期末考试了我还在机房刷题真是不能多说

Code:

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
int a[maxn],b[maxn],c[maxn],n;//a上方,b下方,c中间 
int getint(){
	int res=0;char c=getchar();
	while(!isdigit(c))c=getchar();
	while(isdigit(c))res=res*10+c-'0',c=getchar();
	return res;
}
struct node{
	int lr[2][2];
	int ll,rr;
	node(){
		memset(lr,0,sizeof lr);ll=rr=0;
	}
}t[maxn<<2];
node operator+(const node &ls,const node &rs){
	node C;
	for(int i=0;i<2;i++)for(int j=0;j<2;j++)for(int k=0;k<2;k++)
	C.lr[i][j]|=(ls.lr[i][k]&&rs.lr[k][j])
	||(ls.lr[i][k]&&rs.lr[k^1][j]&&(ls.rr||rs.ll));
	C.ll=ls.ll;C.rr=rs.rr;
	for(int i=0;i<2;i++)for(int j=0;j<2;j++)
	C.ll|=ls.lr[i][j]&&rs.ll&&ls.lr[i^1][j^1],
	C.rr|=rs.lr[i][j]&&ls.rr&&rs.lr[i^1][j^1];
	return C;
}
void Change(int i,int l,int r,int ps){
	if(ps<1||ps>=n)return;
	if(l==r){
		t[i].ll=c[ps]||(a[ps]&&b[ps]&&c[ps+1]);
		t[i].rr=c[ps+1]||(a[ps]&&b[ps]&&c[ps]);
		t[i].lr[0][0]=a[ps]||(b[ps]&&c[ps]&&c[ps+1]);
		t[i].lr[0][1]=(a[ps]&&c[ps+1])||(b[ps]&&c[ps]);
		t[i].lr[1][1]=b[ps]||(a[ps]&&c[ps]&&c[ps+1]);
		t[i].lr[1][0]=(a[ps]&&c[ps])||(b[ps]&&c[ps+1]);;
		return;
	}if(ps<=(l+r)/2)Change(i<<1,l,(l+r)/2,ps);
	else Change(i<<1|1,(l+r)/2+1,r,ps);
	t[i]=t[i<<1]+t[i<<1|1];
}
node Q(int i,int l,int r,int l0,int r0){
	if(l0>r0)return t[0];
	if(l0<=l&&r0>=r)return t[i];
	node L,R;bool le=0,ri=0;
	if(l0<=(l+r)/2)L=Q(i<<1,l,(l+r)/2,l0,r0),le=1;
	if(r0>(l+r)/2)R=Q(i<<1|1,(l+r)/2+1,r,l0,r0),ri=1;
	return (le&&ri)?L+R:(le?L:R);
}
int main(){
	n=getint();
	char s[23];
	while(~scanf("%s",s)){
		if(s[0]=='E')break;
		int x1=getint(),y1=getint(),x2=getint(),y2=getint();
		swap(x1,y1);swap(x2,y2);y1=3-y1;y2=3-y2;
		if(x1>x2)swap(x1,x2),swap(y1,y2);
		if(s[0]=='C'){
//			assert(abs(x1-x2)+abs(y1-y2)==1);
			if(x1==x2)c[x1]=0;else
			if(y1==2)a[x1]=0;else
			if(y1==1)b[x1]=0;
			Change(1,1,n-1,x1-1);
			Change(1,1,n-1,x1);
		}else
		if(s[0]=='O'){
//			assert(abs(x1-x2)+abs(y1-y2)==1);
			if(x1==x2)c[x1]=1;else
			if(y1==2)a[x1]=1;else
			if(y1==1)b[x1]=1;
			Change(1,1,n-1,x1-1);
			Change(1,1,n-1,x1);
		}else
		if(s[0]=='A'){
			if(x1==x2&&y1==y2){puts("Y");continue;}
			y1=2-y1;y2=2-y2;
			if(x1==x2){
				node L=Q(1,1,n-1,1,x1-1);
				node R=Q(1,1,n-1,x1,n-1);
				puts((L.rr||R.ll)?"Y":"N");
				continue;
			}
			x2--;
			node M=Q(1,1,n-1,x1,x2);
			node L=Q(1,1,n-1,1,x1-1);
			node R=Q(1,1,n-1,x2+1,n-1);
//			node LM=L+M,MR=M+R,LR=L+M+R;
			int ans=M.lr[y1][y2];
			ans|=M.ll&&M.lr[y1^1][y2];
			ans|=M.rr&&M.lr[y1][y2^1];
			ans|=M.ll&&M.rr&&M.lr[y1^1][y2^1];
			ans|=L.rr&&M.lr[y1^1][y2];
			ans|=R.ll&&M.lr[y1][y2^1];
			ans|=L.rr&&M.lr[y1^1][y2^1]&&R.ll;
			puts(ans?"Y":"N");
		}	
//		deb(x1);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值