BZOJ 1018: [SHOI2008]堵塞的交通traffic [线段树 区间信息]
1018: [SHOI2008]堵塞的交通traffic
Time Limit: 3 Sec Memory Limit: 162 MB
Submit: 3064 Solved: 1027
[Submit][Status][Discuss]
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
Open 1 1 1 2
Open 1 2 2 2
Ask 1 1 2 2
Ask 2 1 2 2
Exit
Sample Output
N
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define pa t[x].fa
#define lc t[x].ch[0]
#define rc t[x].ch[1]
const int N=2e5+;
inline int read(){
char c=getchar();int x=,f=;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
return x*f;
}
int c;
struct LCTnode{
int ch[],fa,rev;
}t[N];
inline int wh(int x){return t[pa].ch[]==x;}
inline int isRoot(int x){return t[pa].ch[]!=x&&t[pa].ch[]!=x;}
inline void update(int x){
}
inline void rever(int x){
t[x].rev^=;
swap(lc,rc);
}
inline void pushDown(int x){
if(t[x].rev){
rever(lc);
rever(rc);
t[x].rev=;
}
}
inline void rotate(int x){
int f=t[x].fa,g=t[f].fa,c=wh(x);
if(!isRoot(f)) t[g].ch[wh(f)]=x;t[x].fa=g;
t[f].ch[c]=t[x].ch[c^];t[t[f].ch[c]].fa=f;
t[x].ch[c^]=f;t[f].fa=x;
update(f);update(x);
}
int st[N],top;
inline void splay(int x){
top=;st[++top]=x;
for(int i=x;!isRoot(i);i=t[i].fa) st[++top]=t[i].fa;
for(int i=top;i>=;i--) pushDown(st[i]); for(;!isRoot(x);rotate(x))
if(!isRoot(pa)) rotate(wh(x)==wh(pa)?pa:x);
}
inline void Access(int x){
for(int y=;x;y=x,x=pa){
splay(x);
rc=y;
update(x);
}
}
inline void MakeR(int x){
Access(x);splay(x);
rever(x);
}
inline int FindR(int x){
Access(x);splay(x);
while(lc) x=lc;
return x;
}
inline void Link(int x,int y){
MakeR(x);
t[x].fa=y;
}
inline void Cut(int x,int y){
MakeR(x);Access(y);splay(y);
t[y].ch[]=t[x].fa=;
update(y);
} int n;
inline int id(int x,int y){
if(x==) return y;
else return n+y;
}
char s[];
int x1,y1,x2,y2,x,y;
int main(){
freopen("bzoj_1018.in","r",stdin);
//freopen("bzoj_1018.out","w",stdout);
n=read();
while(true){
scanf("%s",s);
if(s[]=='E') break;
x1=read();y1=read();x2=read();y2=read();
x=id(x1,y1);y=id(x2,y2); printf("begin %d %d %d %d %d\n",++c,x1,y1,x,y);
if(s[]=='O') Link(x,y);
if(s[]=='C') if(FindR(x)==FindR(y)) Cut(x,y);
if(s[]=='A'){
if(FindR(x)==FindR(y)) puts("Y");
else puts("N");
}
} }
LCT
正解是线段树,只有两行所以上下一行信息一起维护啊
保存luld,rurd,luru,ldrd,lurd,ldru,up,down up和down是说这段区间和左面的区间上或下是不是连着的
合并和查询参考了Vampire的代码
核心思想是:每个区间最后的信息都是通过这个区间连通之后的
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define mid ((l+r)>>1)
#define lc x<<1
#define rc x<<1|1
#define lson x<<1,l,mid
#define rson x<<1|1,mid+1,r
const int N=2e5+;
inline int read(){
char c=getchar();int x=,f=;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
return x*f;
}
int n,r1,c1,r2,c2;
char op[N];
struct Node{
int luld,rurd,luru,ldrd,lurd,ldru,up,down;
Node():luld(),rurd(),luru(),ldrd(),lurd(),ldru(),up(),down(){}
}t[N<<];
inline Node merge(Node x,Node y){
Node ret;
ret.up=y.up;ret.down=y.down;
ret.luld=x.luld|(x.luru&x.up&y.luld&x.down&x.ldrd);
ret.rurd=y.rurd|(y.luru&x.up&x.rurd&x.down&y.ldrd);
ret.luru=(x.luru&x.up&y.luru) |(x.lurd&x.down&y.ldru);
ret.ldrd=(x.ldrd&x.down&y.ldrd)|(x.ldru&x.up&y.lurd);
ret.lurd=(x.luru&x.up&y.lurd) |(x.lurd&x.down&y.ldrd);
ret.ldru=(x.ldrd&x.down&y.ldru)|(x.ldru&x.up&y.luru);
return ret;
}
void build(int x,int l,int r){
if(l==r) t[x].luru=t[x].ldrd=true;
else{
build(lson);
build(rson);
t[x]=merge(t[lc],t[rc]);//not need
}
}
void segIns1(int x,int l,int r,int c,bool d){
if(l==r) t[x].luld=t[x].rurd=t[x].lurd=t[x].ldru=d;
else{
if(c<=mid) segIns1(lson,c,d);
else segIns1(rson,c,d);
t[x]=merge(t[lc],t[rc]);
}
}
void segIns2(int x,int l,int r,int col,int row,bool d){
if(l==r){
if(row==) t[x].up=d;else t[x].down=d;
}else{
if(col<=mid) segIns2(lson,col,row,d);
else segIns2(rson,col,row,d);
t[x]=merge(t[lc],t[rc]);
}
} Node segQue(int x,int l,int r,int ql,int qr){
if(ql<=l&&r<=qr) return t[x];
else{
Node a,b;int f1=,f2=;
if(ql<=mid) a=segQue(lson,ql,qr),f1=;
if(mid<qr) b=segQue(rson,ql,qr),f2=;
if(f1&&f2) return merge(a,b);
else return f1?a:b;
}
} bool query(){
if(c1>c2) swap(c1,c2),swap(r1,r2);
Node a=segQue(,,n,,c1),b=segQue(,,n,c1,c2),c=segQue(,,n,c2,n);
if(r1==r2){
if(r1==&&( (b.luru)|(c.luld&b.lurd)|(a.rurd&b.ldru)|(a.rurd&b.ldrd&c.luld) )) return true;
if(r1==&&( (b.ldrd)|(c.luld&b.ldru)|(a.rurd&b.lurd)|(a.rurd&b.luru&c.luld) )) return true;
}else{
if(r1==&&( (b.lurd)|(c.luld&b.luru)|(a.rurd&b.ldrd)|(a.rurd&b.ldru&c.luld) )) return true;
if(r2==&&( (b.ldru)|(c.luld&b.ldrd)|(a.rurd&b.luru)|(a.rurd&b.lurd&c.luld) )) return true;
}
return false;
}
int main(){
//freopen("in.txt","r",stdin);
n=read();
build(,,n);
while(true){
scanf("%s",op);
if(op[]=='E') break;
r1=read();c1=read();r2=read();c2=read();
if(op[]=='O'){
if(c1==c2) segIns1(,,n,c1,);
else segIns2(,,n,min(c1,c2),r1,);
}
if(op[]=='C'){
if(c1==c2) segIns1(,,n,c1,);
else segIns2(,,n,min(c1,c2),r1,);
}
if(op[]=='A') printf("%s\n",query()?"Y":"N");
}
}
BZOJ 1018: [SHOI2008]堵塞的交通traffic [线段树 区间信息]的更多相关文章
- BZOJ 1018: [SHOI2008]堵塞的交通traffic(线段树分治+并查集)
传送门 解题思路 可以离线,然后确定每个边的出现时间,算这个排序即可.然后就可以线段树分治了,连通性用并查集维护,因为要撤销,所以要按秩合并,时间复杂度\(O(nlog^2 n)\) 代码 #incl ...
- 【bzoj1018】[SHOI2008]堵塞的交通traffic 线段树区间合并+STL-set
题目描述 给出一张2*n的网格图,初始每条边都是不连通的.多次改变一条边的连通性或询问两个点是否连通. 输入 第一行只有一个整数C,表示网格的列数.接下来若干行,每行为一条交通信息,以单独的一行“Ex ...
- 数据结构(线段树):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 ...
- [BZOJ1018][SHOI2008]堵塞的交通traffic 线段树维护连通性
1018: [SHOI2008]堵塞的交通traffic Time Limit: 3 Sec Memory Limit: 162 MB Submit: 3795 Solved: 1253 [Sub ...
- 【BZOJ1018】[SHOI2008]堵塞的交通traffic 线段树
[BZOJ1018][SHOI2008]堵塞的交通traffic Description 有一天,由于某种穿越现象作用,你来到了传说中的小人国.小人国的布局非常奇特,整个国家的交通系统可以被看成是一个 ...
- [BZOJ 1018] [SHOI2008] 堵塞的交通traffic 【线段树维护联通性】
题目链接:BZOJ - 1018 题目分析 这道题就说明了刷题少,比赛就容易跪..SDOI Round1 Day2 T3 就是与这道题类似的..然而我并没有做过这道题.. 这道题是线段树维护联通性的经 ...
- BZOJ 1018: [SHOI2008]堵塞的交通traffic(线段树)
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1018 用线段树维护区间连通性,对于每一个区间记录6个域表示(左上,左下)(左上,右上)(右上, ...
- bzoj1018[SHOI2008]堵塞的交通traffic——线段树
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1018 巧妙的线段树.维护矩阵四个角的连通性. 考虑两个点连通的可能路径分成3部分:两点左边. ...
随机推荐
- Java简历与面试
尊重原创:http://blog.csdn.net/love_java_cc/article/details/78292347 Java就业指导 想要成为合格的Java程序员或工程师到底需要具备哪 ...
- parseInt原来是这样用的
今天在群里无意中看到了这样一个问题,突然发现不会,结果运行一看,懵逼了,不知道为什么???(结果是啥?自己去试试看) 现在我们还是先来复习一下parseInt()这个知识点吧! parseInt() ...
- ECharts插件的使用
ECharts插件:官网下载echarts.js开发者可以选择源码.下载地址:http://echarts.baidu.com/download.html 下载之后,echarts.js放在js文件夹 ...
- dede的pagelist标签的listsize数字属性详解
转载▼http://blog.sina.com.cn/s/blog_a4f3bd4e01012c8n.html dede的pagelist标签的listsize数字属性详解.见远seo经常用织梦搭建各 ...
- asp.net -mvc框架复习(1)-ASP.NET网站开发概述
1.网站开发的基本步骤: 2.网站开发的需要的知识结构 (1)网站开发前台页面技术 页面设计:HTML .CSS+DIV 页面特效:JavaScript.jQery (2)OOP编程核心公共技能 C ...
- 单KEY业务,数据库水平切分架构实践
本文将以"用户中心"为例,介绍"单KEY"类业务,随着数据量的逐步增大,数据库性能显著降低,数据库水平切分相关的架构实践: 如何来实施水平切分 水平切分后常见的 ...
- Centos硬盘IO性能检测命令iostat[转]
Centos硬盘IO性能检测命令iostat[转] 在Linux下频繁存取文件后,物理内存会很快被用光,当程序结束后,内存不会被正常释放,而是一直作为caching.这个问题,貌似有不少人在问,不过都 ...
- linux下建ftp用户,并限制用户访问路径[转]
目的是:在linux系统上建立ftp用户,并限制其通过ftp访问时,只能访问用户主目录:其主目录显示路径也是“/”,看不到上级目录. 例如,我要建立用户usertest,密码为usertest ...
- Effective Java 第三版——29. 优先考虑泛型
Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...
- 控制台调用天气API例子
第一步,新建控制台应用程序,然后新建类:WeatherReport: using System; using System.Collections.Generic; using System.Linq ...