BZOJ 1018 SHOI2008 堵塞的交通traffic

題意:2*n的網格圖相鄰格點之間有邊,一開始所有邊壞掉了,要求完成以下操作:

1.修復一條邊

2.破壞一條邊

3.詢問兩個格點是否直接或間接聯通

Sol:

神題。。。線段樹維護連通性。感覺我寫了一天+

一開始想線段樹維護一塊內四個角的連通性,開4*4的bool數組合並的時候分類討論/傳遞閉包一下下bulabula

然後一個點怎麼到另一個點呢?

顯然這是可能的

但是還可能這樣

這樣

甚至這樣

於是我們需要取出[1,c1][c1,c2][c2,n]的信息,然後再來一發分類討論/傳遞閉包...

然後第一次寫寫掛了,第二個點有一行錯了其他點都對。。。

今天重寫了一遍,爲了方便只記錄a[2][2]表示左邊2個點與右邊2個點的聯通性,ll,rr表示左/右的連通性up,down表示mid處邊的存在性

然後XJB討論一下,1A啦2333

//其實感覺可以分塊+並查集亂搞??

Code:

#include<bits/stdc++.h>
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define debug(x) cout<<#x<<"="<<x<<endl
using namespace std;
const int maxn = 100009;
struct sg_tree
{
	bool a[2][2];
	bool ll,rr,up,down;
	void cover(bool flag)
	{
		for(int i=0;i<2;i++)
			for(int j=0;j<2;j++)
				a[i][j]=flag;
		ll=flag;rr=flag;
	}
}node[maxn<<2];
typedef sg_tree Block;
int n;
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
Block Merge(bool up,bool down,Block L,Block R)
{
	Block now;now.up=up;now.down=down;
	now.a[0][0]=(L.a[0][0]&&up&&R.a[0][0])||(L.a[0][1]&&down&&R.a[1][0]);
	now.a[0][1]=(L.a[0][0]&&up&&R.a[0][1])||(L.a[0][1]&&down&&R.a[1][1]);
	now.a[1][0]=(L.a[1][0]&&up&&R.a[0][0])||(L.a[1][1]&&down&&R.a[1][0]);
	now.a[1][1]=(L.a[1][0]&&up&&R.a[0][1])||(L.a[1][1]&&down&&R.a[1][1]);
	now.ll=(L.ll)||(L.a[0][0]&&L.a[1][1]&&up&&down&&R.ll);
	now.rr=(R.rr)||(R.a[0][0]&&R.a[1][1]&&up&&down&&L.rr);
	return now;
}
void build(int l,int r,int rt)
{
	if(l==r)
	{
		node[rt].a[0][0]=node[rt].a[1][1]=1;
		return ;
	}int mid=(l+r)>>1;
	build(lson);build(rson);
}
void Change(int l,int r,int rt,int pos,int opt)
{
	if(l==r)
	{
		node[rt].cover(opt);
		node[rt].a[0][0]=node[rt].a[1][1]=1;
		return ;
	}int mid=(l+r)>>1;
	if(pos<=mid) Change(lson,pos,opt);
	else Change(rson,pos,opt);
	node[rt]=Merge(node[rt].up,node[rt].down,node[rt<<1],node[rt<<1|1]);
}
void Modify(int l,int r,int rt,int left,int right,int pos,int opt)
{
	int mid=(l+r)>>1;
	if(right<=mid) Modify(lson,left,right,pos,opt);
	else if(left>mid) Modify(rson,left,right,pos,opt);
	else{if(pos) node[rt].up=opt;else node[rt].down=opt;}
	node[rt]=Merge(node[rt].up,node[rt].down,node[rt<<1],node[rt<<1|1]);
}
Block query(int l,int r,int rt,int left,int right)
{
	if(l==left&&right==r) return node[rt];
	int mid=(l+r)>>1;
	if(right<=mid) return query(lson,left,right);
	else if(left>mid) return query(rson,left,right);
	else return Merge(node[rt].up,node[rt].down,query(lson,left,mid),query(rson,mid+1,right));
}
int main()
{
	n=read();
	build(1,n,1);
	char opt[10];
	while(true)
	{
		scanf("%s",opt+1);
		if(opt[1]=='E') break;
		int r1=read()-1,c1=read(),r2=read()-1,c2=read();
		if(c1>c2) swap(c1,c2),swap(r1,r2);
		if(opt[1]=='O')
		{
			if(c1==c2) Change(1,n,1,c1,1);
			else Modify(1,n,1,c1,c2,r1,1);
		}
		if(opt[1]=='C')
		{
			if(c1==c2) Change(1,n,1,c1,0);
			else Modify(1,n,1,c1,c2,r1,0);
		}
		if(opt[1]=='A')
		{
			r1^=1;r2^=1;
			if(c1==c2)
			{
				Block L=query(1,n,1,1,c1),R=query(1,n,1,c1,n);
				if(L.rr||R.ll) puts("Y");else puts("N");
			}
			else
			{
				Block L=query(1,n,1,1,c1),R=query(1,n,1,c2,n),Mid=query(1,n,1,c1,c2);
				if((Mid.a[r1][r2])||(L.rr&&Mid.a[r1^1][r2])||(R.ll&&Mid.a[r1][r2^1])||(L.rr&&Mid.a[r1^1][r2^1]&&R.ll)) puts("Y");
				else puts("N");
			}
		}
	}
	return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章