在地图上建线段树
[ l , r ] 区间上的线段树节点维护区域间四个顶点的连通性
随手画图差不多就是这四个顶点六条边的连通性
在查询的时候要判断一下左上和左下的点会不会经过左边区域而变得联通起来,右边也是一样
细节很多,挺难写的
#include <cassert>
#include <iostream>
#include <cstdio>
#define N 1000500
using namespace std;
struct Tree{int x1,x2,y1,y2,z1,z2;}tr[4*N],identity;
int a[N][3],b[N],c1,c2,r1,r2,n;
Tree merge(Tree p1,Tree p2,int w) {
Tree tmp = identity;
tmp.x1 = p1.x1 | (p1.y1 & p1.y2 & p2.x1 & a[w][1] & a[w][2]);
tmp.x2 = p2.x2 | (p2.y1 & p2.y2 & p1.x2 & a[w][1] & a[w][2]);
tmp.y1 = (p1.y1 & p2.y1 & a[w][1]) | (p1.z2 & p2.z1 & a[w][2]);
tmp.y2 = (p1.y2 & p2.y2 & a[w][2]) | (p1.z1 & p2.z2 & a[w][1]);
tmp.z1 = (p1.y2 & p2.z1 & a[w][2]) | (p1.z1 & p2.y1 & a[w][1]);
tmp.z2 = (p1.y1 & p2.z2 & a[w][1]) | (p1.z2 & p2.y2 & a[w][2]);
return tmp;
}
void build(int l,int r,int t) {
if (l == r) { tr[t].y1 = tr[t].y2 = 1; return ; }
int mid = (l + r) / 2;
build(l,mid,2*t); build(mid+1,r,2*t+1);
//tr[t] = merge(tr[2*t],tr[2*t+1],mid);
}
void update(int l,int r,int t) {
if (l == r) {
tr[t].x1 = tr[t].x2 = b[c1];
tr[t].z1 = tr[t].z2 = b[c1];
tr[t].y1 = tr[t].y2 = 1;
return ;
}
int mid = (l + r) / 2;
if (c1 <= mid) update(l,mid,2*t);
else update(mid+1,r,2*t+1);
tr[t] = merge(tr[2*t],tr[2*t+1],mid);
}
int ll,rr;
Tree query(int l,int r,int t) {
if (l >= ll && r <= rr) return tr[t];
int mid = (l + r) / 2;
if (ll > mid) return query(mid+1,r,2*t+1);
if (rr <= mid) return query(l,mid,2*t);
return merge(query(l,mid,2*t),query(mid+1,r,2*t+1),mid);
}
int main()
{
scanf("%d",&n);
build(1,n,1);
while (1) {
char cmd[10];
scanf("%s",cmd+1); if (cmd[1] == 'E') break;
scanf("%d%d%d%d",&r1,&c1,&r2,&c2);
if (cmd[1] == 'O' || cmd[1] == 'C') {
if (c1 > c2) swap(r1,r2) , swap(c1,c2);
int p = cmd[1] == 'O' ? 1 : 0;
assert(r1 == r1 || c1 == c2);
if (r1 == r2)
a[c1][r1] = p , update(1,n,1);
else
b[c1] = p , update(1,n,1);
}
if (cmd[1] == 'A') {
if (c1 > c2) swap(r1,r2) , swap(c1,c2);
ll = 1 ; rr = c1;
Tree p1 = query(1,n,1);
ll = c2 ; rr = n;
Tree p2 = query(1,n,1);
ll = c1 ; rr = c2;
Tree p3 = query(1,n,1);
int ans = 0;
if (p1.x2) p3.x1 = 1;
if (p2.x1) p3.x2 = 1;
//p3.x1 |= p1.x2; p3.x2 |= p2.x1;
if (r1 == r2) {
if (r1 == 1) ans = p3.y1 | (p3.x1 & p3.z1) | (p3.x2 & p3.z2) | (p3.x1 & p3.x2 & p3.y2);
if (r1 == 2) ans = p3.y2 | (p3.x1 & p3.z2) | (p3.x2 & p3.z1) | (p3.x1 & p3.x2 & p3.y1);
} else {
if (r1 == 1) ans = p3.z2 | (p3.x1 & p3.y2) | (p3.x2 & p3.y1) | (p3.x1 & p3.x2 & p3.z1);
if (r1 == 2) ans = p3.z1 | (p3.x1 & p3.y1) | (p3.x2 & p3.y2) | (p3.x1 & p3.x2 & p3.z2);
}
if (ans) puts("Y"); else puts("N");
}
}
return 0;
}