题目描述
有一天,由于某种穿越现象作用,你来到了传说中的小人国。小人国的布局非常奇特,整个国家的交通系统可
以被看成是一个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;
输入格式
第一行只有一个整数C,表示网格的列数。接下来若干行,每行为一条交通信息,以单独的一行“Exit”作为
结束。我们假设在一开始所有的道路都是堵塞的。我们保证 C小于等于100000,信息条数小于等于100000。
输出格式
对于每个查询,输出一个“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
这题真TM恶心
线段树维护区间的连通性
需要维护以下的量
(设A,B,C,D是一段区间的左上端点,右上端点,左下端点,右下端点)
upp 区间的中间两列在第1行是否连通
dow 区间的中间两列在第2行是否连通
(A B)
(C D)
l A -> C 是否连通
r B -> D 是否连通
u A -> B 是否连通
d C -> D 是否连通
ud A -> D 是否连通
du B -> C 是否连通
然后区间合并肥肠恶心
一开始自己瞎写姿势不是很对一直30
之后对着题解改了半天发现跟题解差不多了==
#include<cstdio>
#include<algorithm>
const int M = 100005 ;
using namespace std ;
inline int read() {
char c = getchar() ; int x = 0 , w = 1 ;
while(c>'9'||c<'0') { if(c=='-') w = -1 ; c = getchar() ; }
while(c>='0'&&c<='9') { x = x*10+c - '0'; c = getchar() ; }
return x*w ;
}
# define ls now<<1
# define rs now<<1|1
struct Node {
bool upp , dow ;
bool l , r , u , d , ud , du ;
}t[M<<2] ;
inline void pushup(Node &t , Node tl , Node tr) {
t.l = tl.l | (tl.u & t.upp & tr.l & t.dow & tl.d) ;
t.r = tr.r | (tr.u & t.upp & tl.r & t.dow & tr.d) ;
t.u = (tl.u & t.upp & tr.u) | (tl.ud & t.dow & tr.du) ;
t.d = (tl.d & t.dow & tr.d) | (tl.du & t.upp & tr.ud) ;
t.ud = (tl.u & t.upp & tr.ud) | (tl.ud & t.dow & tr.d) ;
t.du = (tl.d & t.dow & tr.du) | (tl.du & t.upp & tr.u) ;
}
void Build(int l , int r , int now) {
if(l == r) {
t[now].upp = t[now].dow = t[now].u = t[now].d = 1 ;
return ;
}
int mid = (l + r)>>1 ;
Build(l , mid , ls) ; Build(mid + 1 , r , rs) ;
}
void Changeh(int x , int h , int val , int l , int r , int now) {
int mid = (l + r)>>1 ;
if(mid == x) {
if(h == 1) t[now].upp = val ;
else t[now].dow = val ;
pushup(t[now] , t[ls] , t[rs]) ;
return ;
}
if(mid >= x) Changeh(x , h , val , l , mid , ls) ;
else Changeh(x , h , val , mid + 1 , r , rs) ;
pushup(t[now] , t[ls] , t[rs]) ;
}
void Changel(int x , int val , int l , int r , int now) {
if(l == r) {
t[now].l = t[now].r = t[now].ud = t[now].du = val ;
return ;
}
int mid = (l + r)>>1 ;
if(mid >= x) Changel(x , val , l , mid , ls) ;
else Changel(x , val , mid + 1 , r , rs) ;
pushup(t[now] , t[ls] , t[rs]) ;
}
Node query(int L , int R , int l , int r , int now) {
if(l >= L && r <= R) return t[now] ;
int mid = (l + r)>>1 ;
if(mid >= R) return query(L , R , l , mid , ls) ;
else if(mid < L) return query(L , R , mid + 1 , r , rs) ;
else {
Node temp = t[now] ;
pushup(temp , query(L , mid , l , mid , ls) , query(mid + 1 , R , mid + 1 , r , rs)) ;
return temp ;
}
}
int main() {
int n = read() ; Build(1 , n , 1) ;
char s[15] ; int r1 , r2 , c1 , c2 ;
scanf("%s",s) ;
while(s[0] != 'E') {
r1 = read() , c1 = read() , r2 = read() , c2 = read() ;
if(c1 > c2) swap(c1 , c2) , swap(r1 , r2) ;
if(s[0] == 'O') {
if(r1 == r2) Changeh(c1 , r1 , 1 , 1 , n , 1) ;
else Changel(c1 , 1 , 1 , n , 1) ;
}
else if(s[0] == 'C') {
if(r1 == r2) Changeh(c1 , r1 , 0 , 1 , n , 1) ;
else Changel(c1 , 0 , 1 , n , 1) ;
}
else if(s[0] == 'A') {
bool Ans = 0 ;
Node l = query(1 , c1 , 1 , n , 1) , x = query(c1 , c2 , 1 , n , 1) , r = query(c2 , n , 1 , n , 1) ;
if(r1 == 1 && r2 == 1) Ans = x.u | (l.r & x.du) | (x.ud & r.l) | (l.r & x.d & r.l) ;
else if(r1 == 1 && r2 == 2) Ans = x.ud | (l.r & x.d) | (x.u & r.l) | (l.r & x.du & r.l) ;
else if(r1 == 2 && r2 == 1) Ans = x.du | (l.r & x.u) | (x.d & r.l) | (l.r & x.ud & r.l) ;
else if(r1 == 2 && r2 == 2) Ans = x.d | (l.r & x.ud) | (x.du & r.l) | (l.r & x.u & r.l) ;
printf(Ans ? "Y
" : "N
") ;
}
scanf("%s",s) ;
}
return 0 ;
}