您的位置:首页 > 其它

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

2018-02-23 21:36 429 查看
【题目描述】

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

HINT

 题解:JudgeOnline/upload/201604/sol(4).rar

Source

【题解】
    思路很妙。

    考虑用线段树维护连通性。

    记 can[2][2] 表示左 上(下) 到右 上(下) 是否连通

    这东西可以用线段树维护查询与更改。

    考虑一条路线,回头(180°转弯)最多有2次(最两端),形状为:
    —— —— ——  S             —— —— —— —— —— —— ——
    |                                        |                                                        |

    —— —— —— —— ——                                        T —— ——

    之类。

    所以先把S,T走到不换行能到的最外侧,然后线段树查询连通性。
/* --------------
user Vanisher
problem bzoj-1018
----------------*/
# include <bits/stdc++.h>
# define ll long long
# define N 100010
using namespace std;
int read(){
int tmp=0, fh=1; char ch=getchar();
while (ch<'0'||ch>'9'){if (ch=='-') fh=-1; ch=getchar();}
while (ch>='0'&&ch<='9'){tmp=tmp*10+ch-'0'; ch=getchar();}
return tmp*fh;
}
struct Tag{
int o[2][2];
};
struct node{
int pr,l,r;
Tag can;
}T[N*3];
int o[2]
,place,n;
char s[11];
Tag mixed(Tag a, Tag b, int lim){
Tag now={0,0,0,0};
for (int i=0; i<=1; i++)
if (o[i][lim]==true){
if (a.o[0][i]&&b.o[i][0]) now.o[0][0]=true;
if (a.o[0][i]&&b.o[i][1]) now.o[0][1]=true;
if (a.o[1][i]&&b.o[i][0]) now.o[1][0]=true;
if (a.o[1][i]&&b.o[i][1]) now.o[1][1]=true;
}
return now;
}
int build(int l, int r){
int p=++place;
T[p].l=l; T[p].r=r;
if (l==r)
T[p].can.o[0][0]=T[p].can.o[1][1]=true;
else {
int mid=(l+r)/2;
build(l,mid);
T[p].pr=build(mid+1,r);
}
return p;
}
void modify1(int p, int x, int tag){
if (T[p].l==T[p].r){
T[p].can.o[0][1]=T[p].can.o[1][0]=tag;
return;
}
int mid=(T[p].l+T[p].r)/2;
if (mid>=x) modify1(p+1,x,tag);
else modify1(T[p].pr,x,tag);
T[p].can=mixed(T[p+1].can,T[T[p].pr].can,mid);
}
void modify0(int p, int x){
if (T[p].r==x) return;
int mid=(T[p].l+T[p].r)/2;
if (mid>=x) modify0(p+1,x);
else modify0(T[p].pr,x);
T[p].can=mixed(T[p+1].can,T[T[p].pr].can,mid);
}
int queryl(int p, int x, int tag){
if (T[p].r==x&&T[p].can.o[tag][tag]==true) return T[p].l;
int mid=(T[p].l+T[p].r)/2;
if (mid<x){
int num=queryl(T[p].pr,x,tag);
if (num!=mid+1) return num;
if (o[tag][mid]==false) return num;
return queryl(p+1,mid,tag);
}
else return queryl(p+1,x,tag);
}
int queryr(int p, int x, int tag){
if (T[p].l==x&&T[p].can.o[tag][tag]==true) return T[p].r;
int mid=(T[p].l+T[p].r)/2;
if (mid>=x){
int num=queryr(p+1,x,tag);
if (num!=mid) return num;
if (o[tag][mid]==false) return num;
return queryr(T[p].pr,mid+1,tag);
}
else return queryr(T[p].pr,x,tag);
}
Tag query(int p, int l, int r){
if (T[p].l==l&&T[p].r==r)
return T[p].can;
int mid=(T[p].l+T[p].r)/2;
if (mid>=r) return query(p+1,l,r);
else if (mid<l) return query(T[p].pr,l,r);
else {
Tag a=query(p+1,l,mid), b=query(T[p].pr,mid+1,r);
return mixed(a,b,mid);
}
}
int main(){
n=read();
int rt=build(1,n);
scanf("\n%s",s+1);
while (s[1]!='E'){
int dx1=read()-1, dy1=read(), dx2=read()-1, dy2=read();
if (dy1>dy2) swap(dy1,dy2), swap(dx1,dx2);
if (s[1]=='O'){
if (dx1!=dx2) modify1(rt,dy1,1);
else {
o[dx1][dy1]=true;
modify0(rt,dy1);
}
}
if (s[1]=='C'){
if (dx1!=dx2) modify1(rt,dy1,0);
else{
o[dx1][dy1]=false;
modify0(rt,dy1);
}
}
if (s[1]=='A'){
dy1=queryl(rt,dy1,dx1);
dy2=queryr(rt,dy2,dx2);
Tag num=query(rt,dy1,dy2);
if (num.o[dx1][dx2]==true)
printf("Y\n"); else printf("N\n")
4000
;
}
scanf("\n%s",s+1);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: