BZOJ1018线段树
Posted Billyshuai
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ1018线段树相关的知识,希望对你有一定的参考价值。
1018: [SHOI2008]堵塞的交通traffic
Time Limit: 3 Sec Memory Limit: 162 MBSubmit: 3489 Solved: 1168
[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
HINT
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int maxn=800000+88; char s[20]; int x1,x2,y1,y2,c; struct Segtree{ struct Status{ int a1[2][2],a2[2]; }s[maxn]; bool b[maxn][2]; int l[maxn],r[maxn],m[maxn]; Status update(Status s1,Status s2,bool b[]) { Status res; for(int i=0;i<=1;++i) for(int j=0;j<=1;++j) res.a1[i][j]=(s1.a1[i][0]&&b[0]&&s2.a1[0][j])||(s1.a1[i][1]&&b[1]&&s2.a1[1][j]); res.a2[0]=(s1.a2[0])||(s1.a1[0][0]&&b[0]&&s2.a2[0]&&b[1]&&s1.a1[1][1]); res.a2[1]=(s2.a2[1])||(s2.a1[0][0]&&b[0]&&s1.a2[1]&&b[1]&&s2.a1[1][1]); return res; } Status access(int x,int y1,int y2){ if(y1<=l[x]&&r[x]<=y2) return s[x]; else if(y2<=m[x]) return access(x<<1,y1,y2); else if(y1>m[x]) return access(x<<1|1,y1,y2); else return update(access(x<<1,y1,y2),access(x<<1|1,y1,y2),b[x]); } void change(bool k,int x,int x1,int y1,int x2,int y2){ if(x1==x2&&y1==m[x]) { b[x][x1]=k; s[x]=update(s[x<<1],s[x<<1|1],b[x]); } else if(l[x]==r[x]) s[x].a1[0][1]=s[x].a1[1][0]=s[x].a2[0]=s[x].a2[1]=k; else { change(k,y2<=m[x]?x<<1:x<<1|1,x1,y1,x2,y2); s[x]=update(s[x<<1],s[x<<1|1],b[x]); } } void ask(int x1,int y1,int x2,int y2){ Status left=access(1,1,y1),right=access(1,y2,c),mid=access(1,y1,y2); bool res=false; for(int i=0;i<=1;++i) for(int j=0;j<=1;++j) if(mid.a1[i][j]&&(i==x1||left.a2[1])&&(j==x2||right.a2[0])) { res=true; break; } if(res) puts("Y"); else puts("N"); } void build(int x,int y1,int y2){ l[x]=y1,r[x]=y2,m[x]=(l[x]+r[x])>>1; if(y1==y2) s[x].a1[0][0]=s[x].a1[1][1]=true; else { build(x<<1,y1,m[x]); build(x<<1|1,m[x]+1,y2); } } }seg; int main(){ scanf("%d",&c); seg.build(1,1,c); while(1){ scanf("%s",s); if(s[0]==\'E\') break; scanf("%d%d%d%d",&x1,&y1,&x2,&y2); --x1;--x2; if(y1>y2) { swap(x1,x2); swap(y1,y2); } if(s[0]==\'O\') seg.change(1,1,x1,y1,x2,y2); else if(s[0]==\'C\') seg.change(0,1,x1,y1,x2,y2); else seg.ask(x1,y1,x2,y2); } return 0; }
以上是关于BZOJ1018线段树的主要内容,如果未能解决你的问题,请参考以下文章
bzoj1018 [SHOI2008]堵塞的交通traffic——线段树
BZOJ 1018: [SHOI2008]堵塞的交通traffic [线段树 区间信息]