bzoj1018 堵塞的交通traffic(线段树)

来源:互联网 发布:gfirefly 调用数据库 编辑:程序博客网 时间:2024/06/10 20:08

题目传送门

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-cnode() {}}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:这道题教练给的标程有问题。反对网上随便找题解!!!

0 0
原创粉丝点击