题意: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;
}