【BZOJ1018】[SHOI2008]堵塞的交通traffic 线段树

【BZOJ1018】[SHOI2008]堵塞的交通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”。

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

题解:先不考虑从两边走的情况,直接上线段树的区间合并即可。用f[0/1][0/1]表示从左上/左下能否走到右上/右下。

那么如果考虑从两边绕的情况呢?一定是贪心的选取第一个能拐的点就直接拐,所以在线段树上找到第一个拐点然后判断中间是否全部连通即可。

#include <cstdio>
#include <cstring>
#include <iostream>
#define lson x<<1
#define rson x<<1|1
using namespace std;
const int maxn=100010;
int n,pre,nxt;
struct node
{
	bool f[2][2],g[3],lp;
	node () {memset(f,0,sizeof(f)),memset(g,0,sizeof(g)),lp=0;}
}s[maxn<<2];
node mix(node a,node b)
{
	node c;
	c.f[0][0]=(a.f[0][0]&b.f[0][0])|(a.f[0][1]&b.f[1][0])|(a.f[0][0]&b.f[1][0]&b.lp)|(a.f[0][1]&b.f[0][0]&b.lp);
	c.f[0][1]=(a.f[0][0]&b.f[0][1])|(a.f[0][1]&b.f[1][1])|(a.f[0][0]&b.f[1][1]&b.lp)|(a.f[0][1]&b.f[0][1]&b.lp);
	c.f[1][0]=(a.f[1][0]&b.f[0][0])|(a.f[1][1]&b.f[1][0])|(a.f[1][0]&b.f[1][0]&b.lp)|(a.f[1][1]&b.f[0][0]&b.lp);
	c.f[1][1]=(a.f[1][0]&b.f[0][1])|(a.f[1][1]&b.f[1][1])|(a.f[1][0]&b.f[1][1]&b.lp)|(a.f[1][1]&b.f[0][1]&b.lp);
	c.g[0]=a.g[0]&b.g[0],c.g[1]=a.g[1]&b.g[1],c.g[2]=a.g[2]|b.g[2],c.lp=a.lp;
	return c;
}
char str[20];
inline int rd()
{
	int ret=0,f=1;	char gc=getchar();
	while(gc<‘0‘||gc>‘9‘)	{if(gc==‘-‘)f=-f;	gc=getchar();}
	while(gc>=‘0‘&&gc<=‘9‘)	ret=ret*10+gc-‘0‘,gc=getchar();
	return ret*f;
}
void updata(int l,int r,int x,int a,int b,int c)
{
	if(l==r)
	{
		s[x].g[b]=c,s[x].f[0][0]=s[x].g[0],s[x].f[1][1]=s[x].g[1],s[x].lp=s[x].g[2];
		s[x].f[0][1]=s[x].g[2]&s[x].f[1][1],s[x].f[1][0]=s[x].g[2]&s[x].f[0][0];
		return ;
	}
	int mid=(l+r)>>1;
	if(a<=mid)	updata(l,mid,lson,a,b,c);
	else	updata(mid+1,r,rson,a,b,c);
	s[x]=mix(s[lson],s[rson]);
}
void getpre(int l,int r,int x,int a)
{
	if(l>a||pre>=r||!s[x].g[2])	return ;
	if(l==r)
	{
		pre=l;
		return ;
	}
	int mid=(l+r)>>1;
	getpre(mid+1,r,rson,a),getpre(l,mid,lson,a);
}
void getnxt(int l,int r,int x,int a)
{
	if(r<a||nxt<=l||!s[x].g[2])	return ;
	if(l==r)
	{
		nxt=l;
		return ;
	}
	int mid=(l+r)>>1;
	getnxt(l,mid,lson,a),getnxt(mid+1,r,rson,a);
}
node query(int l,int r,int x,int a,int b)
{
	if(a>b)
	{
		node tmp;
		tmp.f[0][0]=tmp.f[1][1]=tmp.g[0]=tmp.g[1]=1;
		return tmp;
	}
	if(a<=l&&r<=b)	return s[x];
	int mid=(l+r)>>1;
	if(b<=mid)	return query(l,mid,lson,a,b);
	if(a>mid)	return query(mid+1,r,rson,a,b);
	return mix(query(l,mid,lson,a,b),query(mid+1,r,rson,a,b));
}
int main()
{
	n=rd();
	int a1,b1,a2,b2;
	while(1)
	{
		scanf("%s",str);
		if(str[0]==‘E‘)	return 0;
		a1=rd()-1,b1=rd(),a2=rd()-1,b2=rd();
		if(b1>b2||(b1==b2&&a1>a2))	swap(a1,a2),swap(b1,b2);
		if(str[0]==‘C‘)
		{
			if(b1==b2)	updata(1,n,1,b1,2,0);
			else	updata(1,n,1,b1,a1,0);
		}
		if(str[0]==‘O‘)
		{
			if(b1==b2)	updata(1,n,1,b1,2,1);
			else	updata(1,n,1,b1,a1,1);
		}
		if(str[0]==‘A‘)
		{
			node tmp;
			tmp=query(1,n,1,b1,b2-1);
			if(tmp.f[a1][a2])	printf("Y\n");
			else
			{
				pre=0,getpre(1,n,1,b1);
				nxt=n+1,getnxt(1,n,1,b2);
				node t1,t2;
				if(pre)	t1=query(1,n,1,pre,b1-1);
				if(nxt!=n+1)	t2=query(1,n,1,b2,nxt-1);
				if(t1.g[0]&t1.g[1]&tmp.f[a1^1][a2])	printf("Y\n");
				else	if(t2.g[0]&t2.g[1]&tmp.f[a1][a2^1])	printf("Y\n");
				else	if(t1.g[0]&t1.g[1]&t2.g[0]&t2.g[1]&tmp.f[a1^1][a2^1])	printf("Y\n");
				else	printf("N\n");
			}
		}
	}
}//4 Open 1 1 1 2 Open 1 1 2 1 Open 2 1 2 2 Open 2 2 2 3 Open 2 3 2 4 Open 1 4 2 4 Open 1 3 1 4 Ask 1 2 1 3
时间: 2024-08-09 06:35:23

【BZOJ1018】[SHOI2008]堵塞的交通traffic 线段树的相关文章

bzoj1018: [SHOI2008]堵塞的交通traffic 线段树

线段树维护每一块左上到左下.右上到右下.左上到右上.左下到右下.左上到右下.左下到右上的联通情况. #include<bits/stdc++.h> #define N 100005 #define M (l+r>>1) #define P (k<<1) #define S (k<<1|1) #define K l,r,k #define L l,M,P #define R M+1,r,S #define Z int l=1,int r=n,int k=1 u

bzoj1018 [SHOI2008]堵塞的交通traffic——线段树

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1018 线段树竟然还可以这样用! 维护的是一个矩形内部的连通情况,四个顶点之间有6中连通方式: 因为连通情况具有可合并性,所以可以用线段树来维护! 这篇博客写得很好:https://www.cnblogs.com/DUXT/p/6029815.html 茅塞顿开之后看到这篇博客,觉得写得很好呢:https://www.cnblogs.com/MashiroSky/p/5973686.html

BZOJ 1018: [SHOI2008]堵塞的交通traffic [线段树 区间信息]

1018: [SHOI2008]堵塞的交通traffic Time Limit: 3 Sec  Memory Limit: 162 MBSubmit: 3064  Solved: 1027[Submit][Status][Discuss] Description 有一天,由于某种穿越现象作用,你来到了传说中的小人国.小人国的布局非常奇特,整个国家的交通系统可以被看成是一个2行C列的矩形网格,网格上的每个点代表一个城市,相邻的城市之间有一条道路,所以总共有2C个城市和3C-2条道路. 小人国的交通

BZOJ 1018 SHOI2008 堵塞的交通traffic 线段树

题目大意:给定一张2*n的网格图,多次改变某条边是否可用,多次查询某两个点是否联通 多(yi)年前的我看到这题的第一反应是:这题尼玛能做? 两个点之间的路径可能是这样的: 也可能是这样的: 甚至可能是这样的: 这题能写? 这题其实好写爆了 我们首先忽略第三种情况,假设所有对答案有贡献的边都在两个点的中间 那么我们以每一列为一个叶节点建立线段树 线段树的每个节点开一个二维数组a[2][2] 其中 a[x][y]记录当前区间的左端点的第x行和右端点的第y行是否联通 那么合并如下: 例如,a[0][0

【BZOJ1018】堵塞的交通(线段树)

[BZOJ1018]堵塞的交通(线段树) 题面 Description 有一天,由于某种穿越现象作用,你来到了传说中的小人国.小人国的布局非常奇特,整个国家的交通系统可 以被看成是一个2行C列的矩形网格,网格上的每个点代表一个城市,相邻的城市之间有一条道路,所以总共有2C个 城市和3C-2条道路. 小人国的交通状况非常槽糕.有的时候由于交通堵塞,两座城市之间的道路会变得不连通, 直到拥堵解决,道路才会恢复畅通.初来咋到的你决心毛遂自荐到交通部某份差事,部长听说你来自一个科技高度 发达的世界,喜出

bzoj千题计划108:bzoj1018: [SHOI2008]堵塞的交通traffic

http://www.lydsy.com/JudgeOnline/problem.php?id=1018 关键点在于只有两行 所以一个2*m矩形连通情况只有6种 编号即对应代码中的a数组 线段树维护 用b数组表示 节点第0/1行的最右一列是否连接了右边 来 辅助 节点的合并 查询 对两个点位于矩形的位置分4种情况讨论 两点是否联通,要考虑四种情况 (以两个位置是矩形左上角和右上角为例) 1.直接联通,线段树的节点包含了这种情况,直接判断 2. 3. 4. 后三种情况需要再查询[1,l]和[r,n

Bzoj1018 [SHOI2008]堵塞的交通traffic

Time Limit: 3 Sec  Memory Limit: 162 MBSubmit: 3458  Solved: 1158 Description 有一天,由于某种穿越现象作用,你来到了传说中的小人国.小人国的布局非常奇特,整个国家的交通系统可以被看成是一个2行C列的矩形网格,网格上的每个点代表一个城市,相邻的城市之间有一条道路,所以总共有2C个城市和3C-2条道路. 小人国的交通状况非常槽糕.有的时候由于交通堵塞,两座城市之间的道路会变得不连通,直到拥堵解决,道路才会恢复畅通.初来咋到

bzoj 1018 堵塞的交通traffic 线段树

题意:有一个n * 2的网格图,有3种操作:给两个相邻的点加上一条边,断开相邻的两个点连着的边,询问两个点的连通性. 思路:直接看博客就行了,https://blog.csdn.net/roll_keyboard/article/details/81185535,在纸上画一画来确定4个顶点之间的更新关系.有一个需要注意的细节是有可能通过绕远路的方式可以到达,所以需要考虑前面和后面的部分对询问区间的影响. 代码: #include <bits/stdc++.h> #define ls (o &l

数据结构(线段树):BZOJ 1018: [SHOI2008]堵塞的交通traffic

1018: [SHOI2008]堵塞的交通traffic Time Limit: 3 Sec  Memory Limit: 162 MBSubmit: 2638  Solved: 864 Description 有一天,由于某种穿越现象作用,你来到了传说中的小人国.小人国的布局非常奇特,整个国家的交通系统可以被看成是一个2行C列的矩形网格,网格上的每个点代表一个城市,相邻的城市之间有一条道路,所以总共有2C个城市和3C-2条道路. 小人国的交通状况非常槽糕.有的时候由于交通堵塞,两座城市之间的道