线段树经典题目。判断点的连通性时用分类讨论,x,y,z分别表示横轴 纵轴 斜边 方向的联通性。
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
#define maxn 110000
struct state
{
bool x1,x2,y1,y2,z1,z2;
};
struct node
{
int l,r,m;
state s;
}seg[maxn<<2];
bool edge[maxn<<2][2];
int c;
void build(int l,int r,int rt)
{
seg[rt].l=l;
seg[rt].r=r;
seg[rt].m=(l+r)>>1;
int m=seg[rt].m;
if(l==r)
{
seg[rt].s.x1=seg[rt].s.x2=1;
return;
}
build(l,m,rt<<1);
build(m+1,r,rt<<1|1);
}
state join(state ls,state rs,int mid)
{
state tmp;
tmp.x1=(ls.z1&&edge[mid][1]&&rs.z2)||(ls.x1&&edge[mid][0]&&rs.x1);
tmp.x2=(ls.x2&&edge[mid][1]&&rs.x2)||(ls.z2&&edge[mid][0]&&rs.z1);
tmp.y1=ls.y1||(ls.x1&&edge[mid][0]&&rs.y1&&edge[mid][1]&&ls.x2);
tmp.y2=rs.y2||(rs.x1&&edge[mid][0]&&ls.y2&&edge[mid][1]&&rs.x2);
tmp.z1=(ls.z1&&edge[mid][1]&&rs.x2)||(ls.x1&&edge[mid][0]&&rs.z1);
tmp.z2=(ls.x2&&edge[mid][1]&&rs.z2)||(ls.z2&&edge[mid][0]&&rs.x1);
return tmp;
}
void update(int x1,int y1,int x2,int y2,int rt,int ord)
{
if(x1==seg[rt].l &&x2==seg[rt].r)
{
if(x1==x2&&abs(y1-y2)==1)
{
seg[rt].s.y1=seg[rt].s.y2=seg[rt].s.z1=seg[rt].s.z2=ord;
}
if(x1==x2-1)
{
seg[rt].s=join(seg[rt<<1].s,seg[rt<<1|1].s,seg[rt<<1].r);
}
return;
}
if(x2<=seg[rt].m)
{
update(x1,y1,x2,y2,rt<<1,ord);
}
else if(x1>seg[rt].m)
{
update(x1,y1,x2,y2,rt<<1|1,ord);
}
seg[rt].s=join(seg[rt<<1].s,seg[rt<<1|1].s,seg[rt].m);
}
state get(int rt,int l,int r)
{
if(l==seg[rt].l && seg[rt].r==r)
return seg[rt].s;
if(r<=seg[rt].m)
return get(rt<<1,l,r);
if(seg[rt].m<l)
return get(rt<<1|1,l,r);
return join(get(rt<<1,l,seg[rt].m),get(rt<<1|1,seg[rt].m+1,r),seg[rt].m);
}
bool query(int x1,int y1,int x2,int y2)
{
if(x1==x2&&y1==y2) return true;
if(x1>x2)
{
swap(x1,x2);
swap(y1,y2);
}
state s1,s2,s3;
if(x1>1) s1=get(1,1,x1-1);
s2=get(1,x1,x2);
if(x2<c) s3=get(1,x2+1,c);
if(x1==x2&&s2.y1)return true;
if(x1!=x2&&((y1==1&&y2==1&&s2.x2)||(y1==1&&y2==0&&s2.z2)||(y1==0&&y2==1&&s2.z1)||(y1==0&&y2==0&&s2.x1)))
return true;
if(x1>1&&edge[x1-1][0]&&edge[x1-1][1]&&s1.y2&&((x1==x2)||(y1==1&&y2==1&&s2.z1)||(y1==1&&y2==0&&s2.x1)||(y1==0&&y2==1&&s2.x2)||(y1==0&&y2==0&&s2.z2)))
return true;
if(x2<c&&edge[x2][0]&&edge[x2][1]&&s3.y1&&((x1==x2)||(y1==1&&y2==1&&s2.z2)||(y1==1&&y2==0&&s2.x2)||(y1==0&&y2==1&&s2.x1)||(y1==0&&y2==0&&s2.z1)))
return true;
if(x1>1&&x2<c&&edge[x1-1][0]&&edge[x1-1][1]&&s1.y2&&edge[x2][0]&&edge[x2][1]&&s3.y1&&((x1==x2)||(y1==1&&y2==1&&s2.x1)||(y1==1&&y2==0&&s2.z1)||(y1==0&&y2==1&&s2.z2)||(y1==0&&y2==0&&s2.x2)))
return true;
return false;
}
int main()
{
scanf("%d",&c);
build(1,c,1);
int r1,c1,r2,c2;
char st[20];
while(scanf("%s",st)&&st[0]!='E')
{
scanf("%d%d%d%d",&r1,&c1,&r2,&c2);
if(st[0]=='O')
{
if(c1>c2)
{
swap(c1,c2);
swap(r1,r2);
}
if(c1==c2-1)
edge[c1][r1-1]=true;
update(c1,r1-1,c2,r2-1,1,1);
}
if(st[0]=='C')
{
if(c1>c2)
{
swap(c1,c2);
swap(r1,r2);
}
if(c1==c2-1)
edge[c1][r1-1]=false;
update(c1,r1-1,c2,r2-1,1,0);
}
if(st[0]=='A')
printf("%c\n",query(c1,r1-1,c2,r2-1)?'Y':'N');
}
return 0;
}