题目描述
有一天,由于某种穿越现象作用,你来到了传说中的小人国。小人国的布局非常奇特,整个国家的交通系统可以被看成是一个22行 列的矩形网格,网格上的每个点代表一个城市,相邻的城市之间有一条道路,所以总共有2C2C个城市和3C−23C−2条道路。
小人国的交通状况非常槽糕。有的时候由于交通堵塞,两座城市之间的道路会变得不连通,直到拥堵解决,道路才会恢复畅通。初来咋到的你决心毛遂自荐到交通部某份差事,部长听说你来自一个科技高度发达的世界,喜出望外地要求你编写一个查询应答系统,以挽救已经病入膏肓的小人国交通系统。 小人国的交通部将提供一些交通信息给你,你的任务是根据当前的交通情况回答查询的问题。交通信息可以分为以下几种格式:
Close r1 c1 r2 c2Close r1 c1 r2 c2:相邻的两座城市(r1,c1)(r1,c1)和(r2,c2)(r2,c2)之间的道路被堵塞了;
Open r1 c1 r2 c2Open r1 c1 r2 c2:相邻的两座城市(r1,c1)(r1,c1)和(r2,c2)(r2,c2)之间的道路被疏通了;
Ask r1 c1 r2 c2Ask r1 c1 r2 c2:询问城市(r1,c1)(r1,c1)和(r2,c2)(r2,c2)是否连通。如果存在一条路径使得这两条城市连通,则返回Y,否则返回N。
注:riri表示行数,cici表示列数,1≤ri≤2,1≤ci≤C1≤ri≤2,1≤ci≤C。
输入输出格式
输入格式:
第一行只有一个整数CC,表示网格的列数。接下来若干行,每行为一条交通信息,以单独的一行Exit作为结束。我们假设在一开始所有的道路都是堵塞的。我们保证小于等于100000100000,信息条数小于等于 100000100000。
输出格式:
对于每个查询,输出一个Y或N。
输入输出样例
输入样例#1:
2
Open 1 1 1 2
Open 1 2 2 2
Ask 1 1 2 2
Ask 2 1 2 2
Exit
输出样例#1:
Y
N
说明
数据范围:
对于100%的数据,
1≤C≤1000001≤C≤100000,1≤1≤信息条数 ≤100000≤100000。
分析:我们维护只走在纵坐标为[l,r][l,r]为矩形内的边时,矩形四角的连通性。合并区间还是很好维护的,因为合并两个区间时需要midmid到mid+1mid+1这两条边的连通性,开一个数组记录一下就好了,具体可以看代码。
对于查询从(x,y)(x,y)到(l,r)(l,r)连通性,有44种情况,我们设为(x,y)(x,y)在第yy列的另一个点。
第一种是直接从内矩阵的边走过去;
第二种是先从[1,y][1,y]的矩阵从(x,y)(x,y)走到(!x,y)(!x,y),然后再从[y,r][y,r]的矩阵走到(l,r)(l,r);
第三种是从[y,r][y,r]的矩阵从(x,y)(x,y)走到(!l,r)(!l,r),再从[r,n][r,n]的矩阵走到(l,r)(l,r);
第四种是先从[1,y][1,y]的矩阵从(x,y)(x,y)走到(!x,y)(!x,y),然后再从[y,r][y,r]的矩阵走到(!l,r)(!l,r),再从[r,n][r,n]的矩阵走到(l,r)(l,r)。
代码:
#include <iostream>
#include <cstdio>
#include <cmath>
const int maxn=1e5+7;
using namespace std;
struct node{
int a[4][4];
int l,r;
}t[maxn*4];
int n,a,b,c,d;
int g[maxn*3];
char s[10];
node merge(node x,node y)
{
node z;
int r=x.r;
z.a[0][1]=z.a[1][0]=(x.a[0][1]&g[r]&y.a[0][1])|(x.a[0][3]&g[n+r]&y.a[2][1]);
z.a[0][2]=z.a[2][0]=(x.a[0][2])|(x.a[0][1]&g[r]&y.a[0][2]&g[n+r]&x.a[3][2]);
z.a[0][3]=z.a[3][0]=(x.a[0][1]&g[r]&y.a[0][3])|(x.a[0][3]&g[n+r]&y.a[2][3]);
z.a[1][2]=z.a[2][1]=(x.a[2][1]&g[r]&y.a[0][1])|(x.a[2][3]&g[n+r]&y.a[2][1]);
z.a[1][3]=z.a[3][1]=(y.a[1][3])|(y.a[1][0]&g[r]&x.a[1][3]&g[n+r]&y.a[2][3]);
z.a[2][3]=z.a[3][2]=(x.a[2][1]&g[r]&y.a[0][3])|(x.a[2][3]&g[n+r]&y.a[2][3]);
z.l=x.l;
z.r=y.r;
return z;
}
node neww(int l)
{
node z;
z.l=z.r=l;
z.a[0][1]=z.a[1][0]=z.a[2][3]=z.a[3][2]=1;
z.a[0][2]=z.a[2][0]=z.a[0][3]=z.a[3][0]=z.a[1][2]=z.a[2][1]=z.a[1][3]=z.a[3][1]=g[n*2+l];
return z;
}
void change(int p,int l,int r,int x,int y)
{
if (l==r)
{
t[p]=neww(l);
return;
}
int mid=(l+r)/2;
if (y<=mid) change(p*2,l,mid,x,y);
else if (x>mid) change(p*2+1,mid+1,r,x,y);
else
{
change(p*2,l,mid,x,mid);
change(p*2+1,mid+1,r,mid+1,y);
}
t[p]=merge(t[p*2],t[p*2+1]);
}
node query(int p,int l,int r,int x,int y)
{
if ((l==x) && (r==y)) return t[p];
int mid=(l+r)/2;
if (y<=mid) return query(p*2,l,mid,x,y);
else
{
if (x>mid) return query(p*2+1,mid+1,r,x,y);
else
{
return merge(query(p*2,l,mid,x,mid),query(p*2+1,mid+1,r,mid+1,y));
}
}
}
int main()
{
scanf("%d",&n);
while (1)
{
scanf("%s",s);
if (s[0]=='E') break;
scanf("%d%d%d%d",&a,&b,&c,&d);
if (b>d) swap(a,c),swap(b,d);
if ((s[0]=='O') || (s[0]=='C'))
{
int k;
if (s[0]=='O') k=1;
else k=0;
if (b==d) g[n*2+b]=k;
else
{
if (a==1) g[b]=k;
else g[n+b]=k;
}
change(1,1,n,b,d);
}
if (s[0]=='A')
{
node ans=query(1,1,n,b,d);
node lans=query(1,1,n,1,b);
node rans=query(1,1,n,d,n);
int num1=a*2-2,num2=c*2-1;
int flag=0;
if (ans.a[num1][num2]) flag=1;
if (ans.a[num1^2][num2]&lans.a[1][3]) flag=1;
if (ans.a[num1][num2^2]&rans.a[0][2]) flag=1;
if(ans.a[num1^2][num2^2]&lans.a[1][3]&rans.a[0][2]) flag=1;
if (flag) printf("Y\n");
else printf("N\n");
}
}
}