线段树维护每一块左上到左下、右上到右下、左上到右上、左下到右下、左上到右下、左下到右上的联通情况。
upd:可以直接用3082的方法搞,能过。
#include<bits/stdc++.h>
#define N 100005
#define M (l+r>>1)
#define P (k<<1)
#define S (k<<1|1)
#define K l,r,k
#define L l,M,P
#define R M+1,r,S
#define Z
int l=1,int r=n,int k=1
using namespace std;
int n,m;
struct node{
bool u[2],v[2],a[2];
}a[1<<18];
bool t[2][N];
node merge(node u,node v,Z){
node s[]={u,v},a;
for(int i=0;i!=2;++i){
a.u[i]=s[0].u[i]&&t[i][M]&&s[1].u[i]||s[0].a[i]&&t[i^1][M]&&s[1].a[i^1];
a.v[i]=s[i].v[i]||t[0][M]&&s[i].u[0]&&s[i].u[1]&&t[1][M]&&s[i^1].v[i];
a.a[i]=s[0].u[i]&&t[i][M]&&s[1].a[i]||s[0].a[i]&&t[i^1][M]&&s[1].u[i^1];
}
return a;
}
node query(int s,int t,Z){
return s==l&&t==r?a[k]:t<=M?query(s,t,L):s>M?query(s,t,R):merge(query(s,M,L),query(M+1,t,R),K);
}
bool solve(int s,int t,int i,int j){
node a=query(s,t);
node u=query(1,s);
node v=query(t,n);
return i==j?u.v[1]&&a.u[i^1]&&v.v[0]||a.u[i]:a.u[j]&&u.v[1]||a.u[i]&&v.v[0]||a.a[i]||u.v[1]&&v.v[0]&&a.a[j];
}
void build(Z){
if(l==r)
memset(a[k].u,1,2);
else{
build(L);
build(R);
}
}
void update(Z){
a[k]=merge(a[P],a[S],K);
}
void amend1(int t,Z){
if(l!=r){
if(t<=M)
amend1(t,L);
else
amend1(t,R);
update(K);
}
}
void amend2(int s,int t,Z){
if(l==r){
memset(a[k].v,s,2);
memset(a[k].a,s,2);
}else{
if(t<=M)
amend2(s,t,L);
else
amend2(s,t,R);
update(K);
}
}
int main(){
scanf("%d",&n);
build();
char s[8];
while(scanf("%s",s),*s!='E'){
int u,v,i,j;
scanf("%d%d%d%d",&i,&u,&j,&v);
--i,--j;
if(u>v){
swap(u,v);
swap(i,j);
}
if(*s=='A')
puts(solve(u,v,i,j)?"Y":"N");
else{
bool z=*s=='O';
if(i==j){
t[i][u]=z;
amend1(u);
}else
amend2(z,u);
}
}
}