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

题目传送门

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值