1. 程式人生 > >【BZOJ1018】[SHOI2008]堵塞的交通traffic 線段樹

【BZOJ1018】[SHOI2008]堵塞的交通traffic 線段樹

rdquo fin sof 通信 布局 clu 是否 des 等於

【BZOJ1018】[SHOI2008]堵塞的交通traffic

Description

  有一天,由於某種穿越現象作用,你來到了傳說中的小人國。小人國的布局非常奇特,整個國家的交通系統可以被看成是一個2行C列的矩形網格,網格上的每個點代表一個城市,相鄰的城市之間有一條道路,所以總共有2C個城市和3C-2條道路。 小人國的交通狀況非常槽糕。有的時候由於交通堵塞,兩座城市之間的道路會變得不連通,直到擁堵解決,道路才會恢復暢通。初來咋到的你決心毛遂自薦到交通部某份差事,部長聽說你來自一個科技高度發達的世界,喜出望外地要求你編寫一個查詢應答系統,以挽救已經病入膏肓的小人國交通系統。 小人國的交通部將提供一些交通信息給你,你的任務是根據當前的交通情況回答查詢的問題。交通信息可以分為以下幾種格式:Close r1 c1 r2 c2:相鄰的兩座城市(r1,c1)和(r2,c2)之間的道路被堵塞了;Open r1 c1 r2 c2:相鄰的兩座城市(r1,c1)和(r2,c2)之間的道路被疏通了;Ask r1 c1 r2 c2:詢問城市(r1,c1)和(r2,c2)是否連通。如果存在一條路徑使得這兩條城市連通,則返回Y,否則返回N;

Input

  第一行只有一個整數C,表示網格的列數。接下來若幹行,每行為一條交通信息,以單獨的一行“Exit”作為結束。我們假設在一開始所有的道路都是堵塞的。我們保證 C小於等於100000,信息條數小於等於100000。

Output

  對於每個查詢,輸出一個“Y”或“N”。

Sample Input

2
Open 1 1 1 2
Open 1 2 2 2
Ask 1 1 2 2
Ask 2 1 2 2
Exit

Sample Output

Y
N

題解:先不考慮從兩邊走的情況,直接上線段樹的區間合並即可。用f[0/1][0/1]表示從左上/左下能否走到右上/右下。

那麽如果考慮從兩邊繞的情況呢?一定是貪心的選取第一個能拐的點就直接拐,所以在線段樹上找到第一個拐點然後判斷中間是否全部連通即可。

#include <cstdio>
#include <cstring>
#include <iostream>
#define lson x<<1
#define rson x<<1|1
using namespace std;
const int maxn=100010;
int n,pre,nxt;
struct node
{
	bool f[2][2],g[3],lp;
	node () {memset(f,0,sizeof(f)),memset(g,0,sizeof(g)),lp=0;}
}s[maxn<<2];
node mix(node a,node b)
{
	node c;
	c.f[0][0]=(a.f[0][0]&b.f[0][0])|(a.f[0][1]&b.f[1][0])|(a.f[0][0]&b.f[1][0]&b.lp)|(a.f[0][1]&b.f[0][0]&b.lp);
	c.f[0][1]=(a.f[0][0]&b.f[0][1])|(a.f[0][1]&b.f[1][1])|(a.f[0][0]&b.f[1][1]&b.lp)|(a.f[0][1]&b.f[0][1]&b.lp);
	c.f[1][0]=(a.f[1][0]&b.f[0][0])|(a.f[1][1]&b.f[1][0])|(a.f[1][0]&b.f[1][0]&b.lp)|(a.f[1][1]&b.f[0][0]&b.lp);
	c.f[1][1]=(a.f[1][0]&b.f[0][1])|(a.f[1][1]&b.f[1][1])|(a.f[1][0]&b.f[1][1]&b.lp)|(a.f[1][1]&b.f[0][1]&b.lp);
	c.g[0]=a.g[0]&b.g[0],c.g[1]=a.g[1]&b.g[1],c.g[2]=a.g[2]|b.g[2],c.lp=a.lp;
	return c;
}
char str[20];
inline int rd()
{
	int ret=0,f=1;	char gc=getchar();
	while(gc<‘0‘||gc>‘9‘)	{if(gc==‘-‘)f=-f;	gc=getchar();}
	while(gc>=‘0‘&&gc<=‘9‘)	ret=ret*10+gc-‘0‘,gc=getchar();
	return ret*f;
}
void updata(int l,int r,int x,int a,int b,int c)
{
	if(l==r)
	{
		s[x].g[b]=c,s[x].f[0][0]=s[x].g[0],s[x].f[1][1]=s[x].g[1],s[x].lp=s[x].g[2];
		s[x].f[0][1]=s[x].g[2]&s[x].f[1][1],s[x].f[1][0]=s[x].g[2]&s[x].f[0][0];
		return ;
	}
	int mid=(l+r)>>1;
	if(a<=mid)	updata(l,mid,lson,a,b,c);
	else	updata(mid+1,r,rson,a,b,c);
	s[x]=mix(s[lson],s[rson]);
}
void getpre(int l,int r,int x,int a)
{
	if(l>a||pre>=r||!s[x].g[2])	return ;
	if(l==r)
	{
		pre=l;
		return ;
	}
	int mid=(l+r)>>1;
	getpre(mid+1,r,rson,a),getpre(l,mid,lson,a);
}
void getnxt(int l,int r,int x,int a)
{
	if(r<a||nxt<=l||!s[x].g[2])	return ;
	if(l==r)
	{
		nxt=l;
		return ;
	}
	int mid=(l+r)>>1;
	getnxt(l,mid,lson,a),getnxt(mid+1,r,rson,a);
}
node query(int l,int r,int x,int a,int b)
{
	if(a>b)
	{
		node tmp;
		tmp.f[0][0]=tmp.f[1][1]=tmp.g[0]=tmp.g[1]=1;
		return tmp;
	}
	if(a<=l&&r<=b)	return s[x];
	int mid=(l+r)>>1;
	if(b<=mid)	return query(l,mid,lson,a,b);
	if(a>mid)	return query(mid+1,r,rson,a,b);
	return mix(query(l,mid,lson,a,b),query(mid+1,r,rson,a,b));
}
int main()
{
	n=rd();
	int a1,b1,a2,b2;
	while(1)
	{
		scanf("%s",str);
		if(str[0]==‘E‘)	return 0;
		a1=rd()-1,b1=rd(),a2=rd()-1,b2=rd();
		if(b1>b2||(b1==b2&&a1>a2))	swap(a1,a2),swap(b1,b2);
		if(str[0]==‘C‘)
		{
			if(b1==b2)	updata(1,n,1,b1,2,0);
			else	updata(1,n,1,b1,a1,0);
		}
		if(str[0]==‘O‘)
		{
			if(b1==b2)	updata(1,n,1,b1,2,1);
			else	updata(1,n,1,b1,a1,1);
		}
		if(str[0]==‘A‘)
		{
			node tmp;
			tmp=query(1,n,1,b1,b2-1);
			if(tmp.f[a1][a2])	printf("Y\n");
			else
			{
				pre=0,getpre(1,n,1,b1);
				nxt=n+1,getnxt(1,n,1,b2);
				node t1,t2;
				if(pre)	t1=query(1,n,1,pre,b1-1);
				if(nxt!=n+1)	t2=query(1,n,1,b2,nxt-1);
				if(t1.g[0]&t1.g[1]&tmp.f[a1^1][a2])	printf("Y\n");
				else	if(t2.g[0]&t2.g[1]&tmp.f[a1][a2^1])	printf("Y\n");
				else	if(t1.g[0]&t1.g[1]&t2.g[0]&t2.g[1]&tmp.f[a1^1][a2^1])	printf("Y\n");
				else	printf("N\n");
			}
		}
	}
}//4 Open 1 1 1 2 Open 1 1 2 1 Open 2 1 2 2 Open 2 2 2 3 Open 2 3 2 4 Open 1 4 2 4 Open 1 3 1 4 Ask 1 2 1 3

【BZOJ1018】[SHOI2008]堵塞的交通traffic 線段樹