http://www.elijahqi.win/archives/3425
Description
有一天,由于某种穿越现象作用,你来到了传说中的小人国。小人国的布局非常奇特,整个国家的交通系统可
以被看成是一个2行C列的矩形网格,网格上的每个点代表一个城市,相邻的城市之间有一条道路,所以总共有2C个
城市和3C-2条道路。 小人国的交通状况非常槽糕。有的时候由于交通堵塞,两座城市之间的道路会变得不连通,
直到拥堵解决,道路才会恢复畅通。初来咋到的你决心毛遂自荐到交通部某份差事,部长听说你来自一个科技高度
发达的世界,喜出望外地要求你编写一个查询应答系统,以挽救已经病入膏肓的小人国交通系统。 小人国的交通
部将提供一些交通信息给你,你的任务是根据当前的交通情况回答查询的问题。交通信息可以分为以下几种格式:
Close r1 c1 r2 c2:相邻的两座城市(r1,c1)和(r2,c2)之间的道路被堵塞了;Open r1 c1 r2 c2:相邻的两座城
市(r1,c1)和(r2,c2)之间的道路被疏通了;Ask r1 c1 r2 c2:询问城市(r1,c1)和(r2,c2)是否连通。如果存在一
条路径使得这两条城市连通,则返回Y,否则返回N;
Input
第一行只有一个整数C,表示网格的列数。接下来若干行,每行为一条交通信息,以单独的一行“Exit”作为
结束。我们假设在一开始所有的道路都是堵塞的。我们保证 C小于等于100000,信息条数小于等于100000。
Output
对于每个查询,输出一个“Y”或“N”。
Sample Input
2
Open 1 1 1 2
Open 1 2 2 2
Ask 1 1 2 2
Ask 2 1 2 2
Exit
Sample Output
Y
N
HINT
题解:JudgeOnline/upload/201604/sol(4).rar
Source
感觉足够难写的一题
借用bzoj题解的图
针对每个两行的矩形区域维护线段树 每个区间维护线段树管辖的这个区间的边界的联通情况 即该线段树区域本应该是1,4 那么维护的值就是1和4的连通情况
考虑这个矩形是
s1,s2
s3,s4这样的一个矩形
线段树上维护6个值
U 第一行线段树上区间mid,mid+1的连通情况
D 第二行线段树上区间mid,mid+1的连通情况
u 第一行线段树上区间左端点到右端点的连通情况
d 第二行线段树上区间左端点到右端点的连通情况
l 左端点第一行和第二行的连通情况
r 右端点 第一行和第二行的连通情况
p 刚刚所画矩形s3,s2的联通情况
q 矩形s1,s4的连通情况
剩下在维护的时候我们只考虑是否连通 不用考虑是否走什么样的路线
注意如果l==r的时候即只有上下两个格子的时候要提前把u,d,U,D变成1即可
询问的时候分是否在同一行 分类讨论 因为有可能从外部绕过去 所以询问的时候也需要把 前缀还有后缀的提前处理出来 最后 关于合并的细节 耐心推导看代码
#include<cstdio>
#include<cctype>
#include<algorithm>
#define lc (x<<1)
#define rc (x<<1|1)
using namespace std;
inline int read(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)) {if (ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)) x=x*10+ch-'0',ch=getchar();
return x*f;
}
const int N=1e5+10;
struct node{
int U,D,l,r,u,d,p,q;
}w[N<<2];
char s[10];int n;
inline void build(int x,int l,int r){
if (l==r) {w[x].U=w[x].D=w[x].u=w[x].d=1;return;}
int mid=l+r>>1;build(lc,l,mid);build(rc,mid+1,r);
}
inline void merge(node &x,const node &l,const node &r){
x.l=l.l|(l.u&x.U&r.l&x.D&l.d);
x.r=r.r|(r.u&x.U&l.r&x.D&r.d);
x.u=(l.u&x.U&r.u)|(l.q&x.D&r.p);
x.d=(l.d&x.D&r.d)|(l.p&x.U&r.q);
x.q=(l.u&x.U&r.q)|(l.q&x.D&r.d);
x.p=(l.d&x.D&r.p)|(l.p&x.U&r.u);
// printf("%d %d %d %d %d %d\n",x.l,x.r,x.u,x.d,x.q,x.p);
}
inline void modifyr(int x,int l,int r,int p,int now,int v){
int mid=l+r>>1;
if (mid==p){
if (now==1) w[x].U=v;else w[x].D=v;merge(w[x],w[lc],w[rc]);return;
}
if (p<=mid) modifyr(lc,l,mid,p,now,v);else modifyr(rc,mid+1,r,p,now,v);
merge(w[x],w[lc],w[rc]);
}
inline void modifyc(int x,int l,int r,int p,int v){
if (l==r){w[x].l=w[x].r=w[x].p=w[x].q=v;return;}int mid=l+r>>1;
if (p<=mid) modifyc(lc,l,mid,p,v);else modifyc(rc,mid+1,r,p,v);
merge(w[x],w[lc],w[rc]);
}
inline node query(int x,int l,int r,int l1,int r1){
if(l1<=l&&r1>=r) return w[x];int mid=l+r>>1;
if (r1<=mid) return query(lc,l,mid,l1,r1);
if (l1>mid) return query(rc,mid+1,r,l1,r1);
node tmp=w[x],tmp1=query(lc,l,mid,l1,r1),tmp2=query(rc,mid+1,r,l1,r1);
merge(tmp,tmp1,tmp2);return tmp;
}
int main(){
//freopen("7.in","r",stdin);
// freopen("1.out","w",stdout);
n=read();build(1,1,n);int cnt=0;
while(1){
scanf("%s",s+1);if (s[1]=='E') return 0;
int r1=read(),c1=read(),r2=read(),c2=read();
if (c1>c2) swap(c1,c2),swap(r1,r2);
if (s[1]=='O'){
if (r1==r2) modifyr(1,1,n,c1,r1,1);
else modifyc(1,1,n,c1,1);
}
if (s[1]=='C'){
if (r1==r2) modifyr(1,1,n,c1,r1,0);
else modifyc(1,1,n,c1,0);
}
if (s[1]=='A'){
static node l,x,r;bool ans;//++cnt;if (cnt==12) break;
l=query(1,1,n,1,c1);x=query(1,1,n,c1,c2);r=query(1,1,n,c2,n);
if (r1==1&&r2==1){
ans=x.u|(l.r&x.p)|(x.q&r.l)|(l.r&x.d&r.l);
}
if (r1==1&&r2==2){
ans=x.q|(l.r&x.d)|(x.u&r.l)|(l.r&x.p&r.l);
}
if (r1==2&&r2==1){
ans=x.p|(l.r&x.u)|(x.d&r.l)|(l.r&x.q&r.l);
}
if (r1==2&&r2==2){
ans=x.d|(l.r&x.q)|(x.p&r.l)|(l.r&x.u&&r.l);
}ans?puts("Y"):puts("N");
}
}
return 0;
}