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”。
题解
这道题是几天前的考试题了,今天花了一下午才把它打下来。真讨厌数据结构这种代码长又繁琐的题了。
此题用每个节点表示区间内的连通性(不用区间外的边),edge数组储存每个节点的三条边,之后进行维护就好了。
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int Maxn = 100005;
#define ls (u<<1)
#define rs (u<<1|1)
#define MID(a,b) int mid = (a+b) >> 1;
struct node {
bool a[2], b[2], c[2];
<span style="white-space:pre"> </span>// a x b
<span style="white-space:pre"> </span>// c y d
<span style="white-space:pre"> </span>//a[] means a-c b-d
<span style="white-space:pre"> </span>//b[] means a-b c-d
<span style="white-space:pre"> </span>//c[] means a-d b-c
node() {}
}N[Maxn << 2];
int C, r1, r2, c1, c2;
bool edge[Maxn][3];
void build(int u,int l,int r) {
if (l == r) {
N[u].b[0] = N[u].b[1] = true; return;
}
MID(l,r);
build(ls,l,mid); build(rs,mid+1,r);
}
node pluse(node a, node b,bool x, bool y) {
node c;
c.a[0] = (a.a[0])||(a.b[0]&&a.b[1]&&x&&y&&b.a[0]);
c.a[1] = (b.a[1])||(b.b[0]&&b.b[1]&&x&&y&&a.a[1]);
c.b[0] = (a.b[0]&&x&&b.b[0])||(a.c[0]&&y&&b.c[1]);
c.b[1] = (a.b[1]&&y&&b.b[1])||(a.c[1]&&x&&b.c[0]);
c.c[0] = (x&&a.b[0]&&b.c[0])||(y&&a.c[0]&&b.b[1]);
c.c[1] = (y&&a.b[1]&&b.c[1])||(x&&a.c[1]&&b.b[0]);
return c;
}
void update(int u,int l,int r,int val) {
if (l == r) {
N[u].b[0] = N[u].b[1] = true;
N[u].a[0] = N[u].a[1] = N[u].c[0] = N[u].c[1] = edge[val][2];
return;
}
MID(l,r);
if (val <= mid) update(ls,l,mid,val);
else update(rs,mid+1,r,val);
N[u] = pluse(N[ls],N[rs],edge[mid][0],edge[mid][1]);
}
node query(int u,int l,int r,int x, int y) {
if (l >= x && r <= y) return N[u];
MID(l,r);
if (y <= mid) return query(ls,l,mid,x,y);
else if (x > mid) return query(rs,mid+1,r,x,y);
return pluse(query(ls,l,mid,x,mid),query(rs,mid+1,r,mid+1,y),edge[mid][0],edge[mid][1]);
}
int main() {
//freopen("B.in","r",stdin);
scanf("%d", &C);
build(1,1,C);
char S[10] = {0};
node tmp1, tmp2, tmp3; bool ans;
while (scanf("%s",S)) {
if (*S == 'E') break;
scanf("%d%d%d%d",&r1,&c1,&r2,&c2);
--r1, --r2;
if (c1 > c2) swap(r1,r2), swap(c1,c2);
if (*S == 'O') {
if (r1 > r2) swap(r1,r2), swap(c1,c2);
if (r1 < r2) {
edge[c1][2] = 1; update(1,1,C,c1);
} else {
edge[c1][r1] = 1; update(1,1,C,c1);
}
} else if (*S == 'C') {
if (r1 > r2) swap(r1,r2), swap(c1,c2);
if (r1 < r2) {
edge[c1][2] = 0; update(1,1,C,c1);
} else {
edge[c1][r1] = 0; update(1,1,C,c1);
}
} else {
tmp1 = query(1,1,C,1,c1), tmp2 = query(1,1,C,c1,c2), tmp3 = query(1,1,C,c2,C);
if (r1 && r2) {
ans=tmp2.b[1]||(tmp1.a[1]&&tmp2.c[0])||(tmp2.c[1]&&tmp3.a[0]);
ans = ans || (tmp1.a[1]&&tmp2.b[0]&&tmp3.a[0]);
} else if (! r1 ^ r2) {
ans=tmp2.b[0]||(tmp1.a[1]&&tmp2.c[1])||(tmp2.c[0]&&tmp3.a[0]);
ans = ans || (tmp1.a[1]&&tmp2.b[1]&&tmp3.a[0]);
} else if (r1) {
ans=tmp2.c[1]||(tmp1.a[1]&&tmp2.b[0])||(tmp2.b[1]&&tmp3.a[0]);
ans = ans || (tmp1.a[1]&&tmp2.c[0]&&tmp3.a[0]);
} else {
ans=tmp2.c[0]||(tmp1.a[1]&&tmp2.b[1])||(tmp2.b[0]&&tmp3.a[0]);
ans = ans || (tmp1.a[1]&&tmp2.c[1]&&tmp3.a[0]);
}
if (ans) puts("Y"); else puts("N");
}
}
return 0;
}
ps:这道题教练给的标程有问题。反对网上随便找题解!!!