[BZOJ]1018 堵塞的交通(SHOI2008)
一道有点神的线段树。
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”作为结束。我们假设在一开始所有的道路都是堵塞的。
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
HINT
C,信息条数<=100000。
Solution
修改、询问……首先确定这是一道数据结构题。
可是它每次询问的是两个点的连通性,可持久化并查集?你在逗我?
连通性怎么维护?
我们发现它实质上是在一条线段上进行连通性维护的,即使它有两条,实际上是没有太大区别的。
我们仔细思考一下行数只有1的时候,用数据结构怎么做:
用线段树维护只在该区间影响下,区间两端是否连通,合并起来是毫无压力的。
那么行数为2的时候,我们也试试看这样维护?
我们用线段树维护只在该区间影响下,区间中左上和右上右下,左下和右上右下是否连通,合并起来同样也是没有压力的。
这样我们似乎就解决了询问的问题?
显然这只是其中一种情况,但是还可能有区间外的边影响其连通性的情况:


当然还有更骚的,可以这样:

其实不外乎就是这4种情况,幸好我们都是可以处理的。
你会发现后3种情况我们可以是看作几个区间的共同作用:


这样你就突然发现,每个区间的作用是独立的,也就是说正好是我们所能够维护的。
所以除了上面4项需要维护,我们还需要维护区间左上和左下是否连通,右上和右下是否连通,合并同样很好实现。
这样我们就完美解决了询问操作。
至于修改操作根本就是小case了,小C也大约说一下自己的做法。
更改不同行之间的连通性就是直接改。
然而更改不同列之间的连通性可以动动脑子,我们可以预处理出第i列到第i+1列之间的道路哪个区间更新时会用到它。
例如n=8,第4、5列之间的道路在[1,8]区间更新时被用到;第1、2列之间的道路在[1,2]区间更新时被用到。
很容易证明列间道路和它的更新区间是一一对应的关系。
所以修改某条列间道路时,只要顺着线段树往下找它对应的更新区间,做一次更新操作,再向上更新即可。
时间复杂度O(nlogn*更新常数)。(不知道出题人总时间开3s是什么心态……)
(合并操作写得像豆腐块一样)
#include <cstdio>
#include <cstring>
#include <algorithm>
#define MN 100005
#define l(a) (a<<1)
#define r(a) (a<<1|1)
using namespace std;
const int zx[][]={{,},{,}};
int lk[][MN];
struct node
{
int r; bool a[]; //--\/||
friend node operator+(const node& a,const node& b)
{
node c;
c.r=b.r;
c.a[]=a.a[]&&lk[][a.r]&&b.a[]||a.a[]&&lk[][a.r]&&b.a[];
c.a[]=a.a[]&&lk[][a.r]&&b.a[]||a.a[]&&lk[][a.r]&&b.a[];
c.a[]=a.a[]&&lk[][a.r]&&b.a[]||a.a[]&&lk[][a.r]&&b.a[];
c.a[]=a.a[]&&lk[][a.r]&&b.a[]||a.a[]&&lk[][a.r]&&b.a[];
c.a[]=a.a[]||a.a[]&&a.a[]&&lk[][a.r]&&lk[][a.r]&&b.a[];
c.a[]=b.a[]||b.a[]&&b.a[]&&lk[][a.r]&&lk[][a.r]&&a.a[];
return c;
}
}t[MN<<];
int ct[MN][];
int n; inline int read()
{
int n=,f=; char c=getchar();
while (c<'' || c>'') {if(c=='-')f=-; c=getchar();}
while (c>='' && c<='') {n=n*+c-''; c=getchar();}
return n*f;
} node getitv(int x,int L,int R,int ql,int qr)
{
if (ql==L&&qr==R) return t[x];
int mid=L+R>>;
if (qr<=mid) return getitv(l(x),L,mid,ql,qr);
else if (ql>mid) return getitv(r(x),mid+,R,ql,qr);
else return getitv(l(x),L,mid,ql,mid)+getitv(r(x),mid+,R,mid+,qr);
}
void getcg2(int x,int L,int R,int ql,int qr)
{
if (ql==L&&qr==R) {t[x]=t[l(x)]+t[r(x)]; return;}
int mid=L+R>>;
if (qr<=mid) getcg2(l(x),L,mid,ql,qr);
else if (ql>mid) getcg2(r(x),mid+,R,ql,qr);
t[x]=t[l(x)]+t[r(x)];
}
void getcg1(int x,int L,int R,int q)
{
if (L==R) {t[x].a[]^=; t[x].a[]^=; t[x].a[]^=; t[x].a[]^=; return;}
int mid=L+R>>;
if (q<=mid) getcg1(l(x),L,mid,q); else getcg1(r(x),mid+,R,q);
t[x]=t[l(x)]+t[r(x)];
} void build(int x,int L,int R)
{
if (L==R) {t[x].r=R; t[x].a[]=t[x].a[]=true; return;}
int mid=L+R>>;
ct[mid][]=L; ct[mid][]=R;
build(l(x),L,mid); build(r(x),mid+,R);
t[x]=t[l(x)]+t[r(x)];
} int main()
{
register int x1,y1,x2,y2,g;
char c[];
n=read();
build(,,n);
for (scanf("%s",c);c[]!='E';scanf("%s",c))
{
x1=read()-; y1=read(); x2=read()-; y2=read();
if (c[]=='O'||c[]=='C')
{
if (x1==x2) {g=x1; if (y1>y2) swap(y1,y2);} else g=;
if (lk[g][y1]^(c[]=='C')) continue;
lk[g][y1]^=;
if (g==) getcg1(,,n,y1); else getcg2(,,n,ct[y1][],ct[y1][]);
}
else if (c[]=='A')
{
if (y1>y2) swap(x1,x2),swap(y1,y2);
node lt=getitv(,,n,y1,y2),lt1,lt2;
if (lt.a[zx[x1][x2]]) {puts("Y"); continue;}
if (y1>) lt1=getitv(,,n,,y1-);
if (y2<n) lt2=getitv(,,n,y2+,n);
if (y1>&<.a[zx[!x1][x2]]) if (lk[][y1-]&&lk[][y1-]&<1.a[]) {puts("Y"); continue;}
if (y2<n&<.a[zx[x1][!x2]]) if (lk[][y2 ]&&lk[][y2 ]&<2.a[]) {puts("Y"); continue;}
if (y1>&&y2<n&<.a[zx[!x1][!x2]])
if (lk[][y1-]&&lk[][y1-]&<1.a[]&&lk[][y2 ]&&lk[][y2 ]&<2.a[]) {puts("Y"); continue;}
puts("N");
}
}
}
Last Word
小D当时就丢了一句“大力维护就好了啊”让小C茅塞顿开……
“初来乍到”、“毛遂自荐”、“喜出望外”、“病入膏肓”……出题人的语文水平还是值得肯定的。
[BZOJ]1018 堵塞的交通(SHOI2008)的更多相关文章
- BZOJ 1018 堵塞的交通
Description 有一天,由于某种穿越现象作用,你来到了传说中的小人国.小人国的布局非常奇特,整个国家的交通系统可以被看成是一个2行C列的矩形网格,网格上的每个点代表一个城市,相邻的城市之间有一 ...
- BZOJ 1018 堵塞的交通traffic(线段树)
题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1018 题意:一个2*n的格子,相邻格子之间有一条道路.初始时道路是不通的. 三种操作:( ...
- 【BZOJ】【1018】【SHOI2008】堵塞的交通traffic
线段树 这题的线段树+分类讨论蛮神奇的……我以前学的线段树简直就是渣渣QAQ 看了下ydc题解里的思想>_>用线段树维护连通性!那么就自己写吧……每个节点表示一段区间的连通性(我的叶子节点 ...
- 数据结构(线段树):BZOJ 1018: [SHOI2008]堵塞的交通traffic
1018: [SHOI2008]堵塞的交通traffic Time Limit: 3 Sec Memory Limit: 162 MBSubmit: 2638 Solved: 864 Descri ...
- BZOJ 1018 [SHOI2008]堵塞的交通traffic
1018: [SHOI2008]堵塞的交通traffic Time Limit: 3 Sec Memory Limit: 162 MBSubmit: 2247 Solved: 706[Submit ...
- BZOJ 1018: [SHOI2008]堵塞的交通traffic [线段树 区间信息]
1018: [SHOI2008]堵塞的交通traffic Time Limit: 3 Sec Memory Limit: 162 MBSubmit: 3064 Solved: 1027[Submi ...
- [BZOJ 1018] [SHOI2008] 堵塞的交通traffic 【线段树维护联通性】
题目链接:BZOJ - 1018 题目分析 这道题就说明了刷题少,比赛就容易跪..SDOI Round1 Day2 T3 就是与这道题类似的..然而我并没有做过这道题.. 这道题是线段树维护联通性的经 ...
- bzoj千题计划108:bzoj1018: [SHOI2008]堵塞的交通traffic
http://www.lydsy.com/JudgeOnline/problem.php?id=1018 关键点在于只有两行 所以一个2*m矩形连通情况只有6种 编号即对应代码中的a数组 线段树维护 ...
- 1018: [SHOI2008]堵塞的交通traffic
1018: [SHOI2008]堵塞的交通traffic 链接 分析: 用线段树维护区间的四个端点的联通情况,然后查询的时候,把所有覆盖到的区间合并起来即可. 六种情况左上到右上(左边到右边的情况)… ...
随机推荐
- Web前端性能分析
Web前端性能通常上代表着一个完全意义上的用户响应时间,包含从开始解析HTML文件到最后渲染完成开始的整个过程,但不包括在输入url之后与服务器的交互阶段.下面是整个过程的各个步骤: 开始解析html ...
- System.Reflection名称空间下的程序集类Assembly应用.
利用反射中的程序集类(Assembly--抽象类)动态加载类库(.dll)或者可执行程序(.exe). 优点:①.可以消除if条件的逻辑判断.②.减少内存资源.③.有利于程序扩展. 缺点... 使用静 ...
- cocos2d 判断旋转矩形是否包含某个点
本来想画个图演示一下,但是折腾了一会发现画不好,我的win10系统没有安装office,以后再看的话再补上吧.不废话了. 如图所以,如果判断点P是否被矩形A所包含,非常容易.那么如果矩形A以中心点逆时 ...
- sublimeText3 中配置sass环境,并将编译后文件保存到指定文件夹
sass基于ruby引擎,所以安装时ass.compass之前需要安装ruby.具体的链接应该是(http://rubyinstaller.org/downloads).下载并安装相应的版本,勾选第二 ...
- node.js的安装的配置
一.Node.js 安装配置 Node.js 提供在Windows和Linux上安装 1. Window 上安装Node.js 64 位安装包下载地址 : https://nodejs.org/di ...
- Spring Security入门(2-3)Spring Security 的运行原理 3
关键组件关系 FilterSecurityInterceptor--- authenticationManager --- UserDetailService--- accessDecisionMan ...
- 模板引擎Jade详解
有用的符号: | 竖杠后的字符会被原样输出 · 点表示下一级的所有字符都会被原样输出,不再被识别.(就是|的升级版,实现批量) include 表示引用外部文件 短杠说明后面跟着的字符只是一段代码(与 ...
- LayUI之table数据表格获取行、行高亮等相关操作
前言 目前LayUI数据表格既美观有不乏一些实用功能.基本上表格应有的操作已经具备,LayUI作者[贤心]肯定是煞费苦心去优化,此处致敬.但是实话实话,如果单纯那数据表格功能来说,EasUI的数据表格 ...
- VCS使用学习笔记(0)——写在前面的话
由于毕业设计做的是数字IC相关,虽然不是纯设计,但是也有设计相关.有设计就要有仿真验证,我就趁此机会来学习一下VCS的使用吧.当然,这里只是学习其简单的逻辑仿真功能,从波形仿真到覆盖率等,基本上不涉其 ...
- Java中对List去重, Stream去重
问题 当下互联网技术成熟,越来越多的趋向去中心化.分布式.流计算,使得很多以前在数据库侧做的事情放到了Java端.今天有人问道,如果数据库字段没有索引,那么应该如何根据该字段去重?大家都一致认为用Ja ...