【BZOJ】【1018】【SHOI2008】堵塞的交通traffic

线段树



  这题的线段树+分类讨论蛮神奇的……我以前学的线段树简直就是渣渣QAQ

  看了下ydc题解里的思想>_>用线段树维护连通性!那么就自己写吧……每个节点表示一段区间的连通性(我的叶子节点表示的是一个方块型的四个点之间的连通性,所以我直接n--了)对线段树上每个节点维护6个信息,即四个端点中任意一对点之间的连通性。

  维护连通性的时候要进行信息的整合,也就是说间接连通的要全部找到并标记上连通,举个例子:如果左边连通且下边两端点连通,则左上到右下连通。这是一个简单的讨论我就不细说了,自己想一下真的很容易<_<。

  但是这时候我遇到了一个蛋疼的问题:对于叶子节点来说,如果我上下左右四条边都连着,那么肯定是完全连通的……但是如果这时候我删一条边(Close)该怎么办?因为连通性并没有任何变化,但是图跟原来不一样了……所以我选择单独开一个a数组存叶子的直接连通情况(也就是存原图)然后用线段树t维护直接间接连通。

  

  好的这个时候这个线段树我们就维护好了,那么查询的时候就方便啦~我们可以查询一下L=[1,c1-1]这个区间的右端点是否连通

(保证了这种情况:

  查询一下R=[c2,n]这个区间左端点是否连通,跟上图类似,是在右边连通的

  最后再查询一下mid=[c1,c2-1]这个区间的连通情况,如果L的右端点连通,则mid的左端点是连通的,mid的右端点同理(R的左端点)

  然后重新维护下mid的连通情况……OK啦~

  这题写的好辛苦……分类讨论总是想不清……

  最后给个样例图吧~(红色的为查询点)

  1 /**************************************************************
  2     Problem: 1018
  3     User: Tunix
  4     Language: C++
  5     Result: Accepted
  6     Time:1068 ms
  7     Memory:4208 kb
  8 ****************************************************************/
  9
 10 //BZOJ 1018
 11 #include<vector>
 12 #include<cstdio>
 13 #include<cstring>
 14 #include<cstdlib>
 15 #include<iostream>
 16 #include<algorithm>
 17 #define rep(i,n) for(int i=0;i<n;++i)
 18 #define F(i,j,n) for(int i=j;i<=n;++i)
 19 #define D(i,j,n) for(int i=j;i>=n;--i)
 20 #define pb push_back
 21 using namespace std;
 22 inline int getint(){
 23     int v=0,sign=1; char ch=getchar();
 24     while(ch<‘0‘||ch>‘9‘){ if (ch==‘-‘) sign=-1; ch=getchar();}
 25     while(ch>=‘0‘&&ch<=‘9‘){ v=v*10+ch-‘0‘; ch=getchar();}
 26     return v*sign;
 27 }
 28 const int N=1e5+10,INF=~0u>>2;
 29 typedef long long LL;
 30 /******************tamplate*********************/
 31 int n;
 32 struct node{
 33     bool z,y,s,x,zs,zx;
 34     node(bool z=0,bool y=0,bool s=0,bool x=0,bool zs=0,bool zx=0):
 35         z(z),y(y),s(s),x(x),zs(zs),zx(zx){}
 36     //z 左端两结点是否连通
 37     //y 右端
 38     //s 上方
 39     //x 下方
 40     //zs 左上->右下
 41     //zx 左下->右上
 42 }a[N],t[N<<2],ans;
 43 #define L (o<<1)
 44 #define R (o<<1|1)
 45 #define mid (l+r>>1)
 46 void maintain(node &a){
 47     a.zs|=(a.z&a.x) | (a.s&a.y);
 48     a.zx|=(a.z&a.s) | (a.x&a.y);
 49     a.z|=(a.zs&a.x) | (a.zx&a.s);
 50     a.y|=(a.zs&a.s) | (a.zx&a.x);
 51     a.s|=(a.zs&a.y) | (a.zx&a.z);
 52     a.x|=(a.zs&a.z) | (a.zx&a.y);
 53 }
 54 node Union(node x,node y){
 55     node tmp;
 56     tmp.z =x.z; tmp.y=y.y;
 57     tmp.s =(x.s&y.s)  | (x.zs&y.zx) ;
 58     tmp.x =(x.x&y.x)  | (x.zx&y.zs) ;
 59     tmp.zs=(x.s&y.zs) | (x.zs&y.x) ;
 60     tmp.zx=(x.x&y.zx) | (x.zx&y.s) ;
 61     return tmp;
 62 }
 63 void update(int o,int l,int r,int pos,int num,bool v){
 64 //将pos位置的num号连通情况改为v
 65     if (l==r){
 66         if (num==1) a[l].z=v; if (num==2) a[l].y=v;
 67         if (num==3) a[l].s=v; if (num==4) a[l].x=v;
 68         t[o]=a[l];
 69     }else{
 70         if (pos<=mid) update(L,l,mid,pos,num,v);
 71         else update(R,mid+1,r,pos,num,v);
 72         t[o]=Union(t[L],t[R]);
 73     }
 74     maintain(t[o]);
 75 }
 76 int ql,qr;bool sign=0;
 77 void query(int o,int l,int r){
 78     if (ql<=l && qr>=r){
 79         if (!sign) {ans=t[o];sign=1;}
 80         else ans=Union(ans,t[o]);
 81     }
 82     else{
 83         if (ql<=mid) query(L,l,mid);
 84         if (qr>mid) query(R,mid+1,r);
 85     }
 86 }
 87 int main(){
 88 #ifndef ONLINE_JUDGE
 89     freopen("1018.in","r",stdin);
 90     freopen("1018.out","w",stdout);
 91 #endif
 92     n=getint()-1;
 93     int r1,r2,c1,c2;
 94     char cmd[10];
 95     while(scanf("%s",cmd)!=EOF && cmd[0]!=‘E‘){
 96         r1=getint(); c1=getint(); r2=getint(); c2=getint();
 97         if (c1>c2){swap(c1,c2); swap(r1,r2);}
 98         if (cmd[0]==‘A‘){
 99             ans=node();
100             if (c1==c2){
101                 if (c1<n+1 && c1>1){//不是右端点
102                     node t1,t2;
103                     ql=1; qr=c1-1; sign=0;
104                     query(1,1,n); t1=ans;
105                     ql=c1; qr=n; sign=0;
106                     query(1,1,n);
107                     ans.z|=t1.y; ans.z|=t2.z;
108                     puts(ans.z?"Y":"N");
109                 }else if(c1==n+1){
110                     ans=t[1];
111                     puts(ans.y?"Y":"N");
112                 }else{
113                     ans=t[1];
114                     puts(ans.z?"Y":"N");
115                 }
116             }else{
117                 node t1,t2;
118                 if (c1!=1){ql=1; qr=c1-1; sign=0; query(1,1,n); t1=ans;}
119                 if (c2!=n+1){ql=c2; qr=n; sign=0; query(1,1,n); t2=ans;}
120                 ql=c1; qr=c2-1; sign=0;
121                 query(1,1,n);
122                 ans.z|=t1.y | (t1.s & t1.z & t1.x);
123                 ans.y|=t2.z | (t2.s & t2.y & t2.x);
124                 maintain(ans);
125                 if (r1==1 && r2==1) puts(ans.s ?"Y":"N");
126                 if (r1==2 && r2==2) puts(ans.x ?"Y":"N");
127                 if (r1==1 && r2==2) puts(ans.zs?"Y":"N");
128                 if (r1==2 && r2==1) puts(ans.zx?"Y":"N");
129             }
130         }else{
131             bool type=0;
132             if (cmd[0]==‘O‘) type=1;
133             else type=0;
134             if (r1==r2){
135                 if (r1==1) update(1,1,n,c1,3,type);
136                 else update(1,1,n,c1,4,type);
137             }else{
138                 if (c1<n+1) update(1,1,n,c1,1,type);
139                 if (c1>1  ) update(1,1,n,c1-1,2,type);
140             }
141         }
142     }
143     return 0;
144 }
145 

1018: [SHOI2008]堵塞的交通traffic

Time Limit: 3 Sec  Memory Limit: 162 MB
Submit: 2030  Solved: 638
[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”作为结束。我们假设在一开始所有的道路都是堵塞的。
对30%测试数据,我们保证C小于等于1000,信息条数小于等于1000; 对100%测试数据,我们保证
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

Source

[Submit][Status][Discuss]

时间: 2024-10-10 04:13:41

【BZOJ】【1018】【SHOI2008】堵塞的交通traffic的相关文章

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

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

[BZOJ 1018] [SHOI2008] 堵塞的交通traffic 【线段树维护联通性】

题目链接:BZOJ - 1018 题目分析 这道题就说明了刷题少,比赛就容易跪..SDOI Round1 Day2 T3 就是与这道题类似的..然而我并没有做过这道题.. 这道题是线段树维护联通性的经典模型. 我们线段树的一个节点表示一个区间的联通性,有 6 个 bool 值,表示这个区间的 4 个角上的点之间的联通性. 然后用两个子区间的联通性和两个子区间之间的连边情况合并出整个区间的联通性. 修改某条边时,先在边的数组中修改,然后从这条边所在的点的线段树叶子开始向上 Update . 询问两

[BZOJ 1018][SHOI2008]堵塞的交通traffic(线段树)

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

bzoj 1018: [SHOI2008]堵塞的交通traffic

由于只有两行,对一个区间可以维护四个角上的连通性 一共6个量,满足区间可加性,用线段树维护,查询时找出3段的量,看是否满足题解上的三种情况之一. 1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<cstdlib> 5 #include<cmath> 6 #include<queue> 7 #include<algorithm> 8

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

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

1018: [SHOI2008]堵塞的交通traffic

1018: [SHOI2008]堵塞的交通traffic 链接 分析: 用线段树维护区间的四个端点的联通情况,然后查询的时候,把所有覆盖到的区间合并起来即可. 六种情况左上到右上(左边到右边的情况)……,左上到左下(同一侧相互到达的情况)…… 同一侧相互到达的情况,查询[l,r]是查的不完全.因为还有可能是先往左边走几步,下去,在走回来.这时候,查询一下[1,l]的情况,或起来即可. 代码: 1 #include<cstdio> 2 #include<algorithm> 3 #i

【BZOJ】1018: [SHOI2008]堵塞的交通traffic

http://www.lydsy.com/JudgeOnline/problem.php?id=1018 题意:有2行,每行有c(c<=100000)个城市,则一共有c-1个格子,现在有q(q<=100000)个操作,操作Open和Close是将格子的四个角相邻的城市连边或删边,操作Ask是询问两个城市是否连通 #include <cstdio> #include <cstring> #include <cmath> #include <string&

【SHOI 2008】【BZOJ 1018】堵塞的交通traffic

发现很多有关区间联通问题的题线段树都可以做,不论是1列还是2列.这题的易错点在于两个端点x,y之间的可行路径不一定在区间[x,y]之间,有可能是从其他区间绕过来的,想明白这一点,区间的更新又与1列的情况基本类似,这题就很好做了. code: #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define mid (l+r)/2 #define lch i<

【BZOJ 1018】 [SHOI2008]堵塞的交通traffic

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