BZOJ 1018

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

一道很恶心的数据结构题,但是数据结构却很简单,就是一颗裸的线段树。然而,用线段树维护连通性却很恶心(因为它只有相邻的两个点之间有连边)。我的线段树维护了8个域——左右,上下,对角,中间。慢慢写,反正我是写醉了。

奉劝:(代码仅限对拍,莫看莫看)

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstdlib>
  4 using namespace std;
  5
  6 #define maxn 100010
  7 int n;
  8 struct node
  9 {
 10     int lc,rc,l,r;
 11     bool u[3]; //左上-左下    右上-右下
 12     bool v[3]; //左上-右上    左下-右下
 13     bool w[3]; //左下-右上    左上-右下
 14     bool t[3]; //中间的两个
 15 };
 16 struct SEG
 17 {
 18     int cnt; node tree[maxn*8];
 19
 20     inline void updata(int now,bool flag)
 21     {
 22         tree[now].w[1] = tree[now].w[2] = false;
 23         if (!flag) if (tree[now].l != tree[now].r) tree[now].u[1] = tree[now].u[2] = false,tree[now].v[1] = tree[now].v[2] = false;
 24         int lc = tree[now].lc,rc = tree[now].rc; bool sign = false;
 25         do
 26         {
 27             sign = false;
 28             if (!tree[now].u[1])
 29             {
 30                 if (tree[now].v[1]&&tree[now].w[1])
 31                     tree[now].u[1] = true,sign = true;
 32                 else if (tree[now].v[2]&&tree[now].w[2])
 33                     tree[now].u[1] = true,sign = true;
 34                 else if (tree[now].u[2]&&tree[now].v[1]&&tree[now].v[2])
 35                     tree[now].u[1] = true,sign = true;
 36                 else if (tree[lc].u[1]) tree[now].u[1] = true,sign = true;
 37             }
 38             if (!tree[now].u[2])
 39             {
 40                 if (tree[now].v[1]&&tree[now].w[2])
 41                     tree[now].u[2] = true,sign = true;
 42                 else if (tree[now].v[2]&&tree[now].w[1])
 43                     tree[now].u[2] = true,sign = true;
 44                 else if (tree[now].u[1]&&tree[now].v[1]&&tree[now].v[2])
 45                     tree[now].u[2] = true,sign = true;
 46                 else if (tree[rc].u[2]) tree[now].u[2] = true,sign = true;
 47             }
 48             if (!tree[now].v[1])
 49             {
 50                 if (tree[now].r - tree[now].l == 1 && tree[now].t[1])
 51                     tree[now].v[1] = true,sign = true;
 52                 else if (tree[now].u[1]&&tree[now].w[1])
 53                     tree[now].v[1] = true,sign = true;
 54                 else if (tree[now].u[2]&&tree[now].w[2])
 55                     tree[now].v[1] = true,sign = true;
 56                 else if (tree[lc].v[1]&&tree[rc].v[1]&&tree[now].t[1])
 57                     tree[now].v[1] = true,sign = true;
 58                 else if (tree[lc].w[2]&&tree[now].t[2]&&tree[rc].w[1])
 59                     tree[now].v[1] = true,sign = true;
 60             }
 61             if (!tree[now].v[2])
 62             {
 63                 if (tree[now].r - tree[now].l == 1 && tree[now].t[2])
 64                     tree[now].v[2] = true,sign = true;
 65                 if (tree[now].u[1]&&tree[now].w[2])
 66                     tree[now].v[2] = true,sign = true;
 67                 else if (tree[now].u[2]&&tree[now].w[1])
 68                     tree[now].v[2] = true,sign = true;
 69                 else if (tree[lc].v[2]&&tree[rc].v[2]&&tree[now].t[2])
 70                     tree[now].v[2] = true,sign = true;
 71                 else if (tree[lc].w[1]&&tree[now].t[1]&&tree[rc].w[2])
 72                     tree[now].v[2] = true,sign = true;
 73             }
 74             if (!tree[now].w[1])
 75             {
 76                 if (tree[now].u[1]&&tree[now].v[1])
 77                     tree[now].w[1] = true,sign = true;
 78                 else if (tree[now].u[2]&&tree[now].v[2])
 79                     tree[now].w[1] = true,sign = true;
 80                 else if (tree[lc].w[1]&&tree[now].t[1]&&tree[rc].v[1])
 81                     tree[now].w[1] = true,sign = true;
 82                 else if (tree[lc].v[2]&&tree[now].t[2]&&tree[now].w[1])
 83                     tree[now].w[1] = true,sign = true;
 84             }
 85             if (!tree[now].w[2])
 86             {
 87                 if (tree[now].u[1]&&tree[now].v[2])
 88                     tree[now].w[2] = true,sign = true;
 89                 else if (tree[now].u[2]&&tree[now].v[1])
 90                     tree[now].w[2] = true,sign = true;
 91                 else if (tree[lc].w[2]&&tree[now].t[2]&&tree[rc].v[2])
 92                     tree[now].w[2] = true,sign = true;
 93                 else if (tree[lc].v[1]&&tree[now].t[1]&&tree[rc].w[2])
 94                     tree[now].w[2] = true,sign = true;
 95             }
 96         }
 97         while (sign);
 98         if (tree[now].l == tree[now].r)
 99             tree[now].w[1] = tree[now].w[2] = false;
100     }
101
102     inline int build(int l,int r)
103     {
104         int now = ++cnt,mid = (l + r) >> 1;
105         tree[now].l = l; tree[now].r = r;
106         if (l == r)
107         {
108             tree[now].v[1] = tree[now].v[2] = true;
109             updata(now,1);
110             return now;
111         }
112         tree[now].lc = build(l,mid);
113         tree[now].rc = build(mid+1,r);
114         updata(now,1);
115         return now;
116     }
117
118     inline bool ask(int a1,int b1,int a2,int b2,int now)
119     {
120         if (a1 == a2 && b1 == b2) return true;
121         int l = tree[now].l,r = tree[now].r,lc = tree[now].lc,rc = tree[now].rc,mid = (l + r) >> 1;
122         if (b1 == l&&b2 == r)
123         {
124             if (a1 == a2 && tree[now].v[a1]) return true;
125             if (a1 != a2)
126             {
127                 if (a1 == 1 && tree[now].w[2]) return true;
128                 if (a1 == 2 && tree[now].w[1]) return true;
129                 if (l == r && tree[now].u[1]) return true;
130             }
131         }
132         else if (b2 <= mid && ask(a1,b1,a2,b2,lc)) return true;
133         else if (b1 > mid && ask(a1,b1,a2,b2,rc)) return true;
134         else if (mid >= b1 && mid < b2 && tree[now].t[1]&&ask(a1,b1,1,mid,lc)&&ask(1,mid+1,a2,b2,rc)) return true;
135         else if (mid >= b1 && mid < b2 && tree[now].t[2]&&ask(a1,b1,2,mid,lc)&&ask(2,mid+1,a2,b2,rc)) return true;
136         else if (a1 != a2 && tree[now].t[1] && tree[now].t[2])
137         {
138             if (b2 <= mid) return tree[rc].u[1]&&ask(a1,b1,a1,mid,lc)&&ask(a2,b2,a2,mid,lc);
139             else if (b1 > mid) return tree[lc].u[2]&&ask(a1,mid+1,a1,b1,rc)&&ask(a2,mid+1,a2,b2,rc);
140         }
141         else if (a1 == a2 && tree[now].t[1]&&tree[now].t[2])
142         {
143             if (b2 <= mid)
144                 return tree[rc].u[1]&&ask(a1,b1,((a1-1)^1)+1,b1,lc)&&ask(((a1-1)^1)+1,b1,((a1-1)^1)+1,mid,lc)&&ask(a2,b2,a2,mid,lc);
145             else if (b1 > mid)
146                 return tree[lc].u[2]&&ask(a1,b2,((a1-1)^1)+1,b2,rc)&&ask(((a1-1)^1)+1,mid+1,((a1-1)^1)+1,b2,rc)&&ask(a2,mid+1,a2,b1,rc);
147         }
148         return false;
149     }
150
151     inline void modify(int a1,int b1,int a2,int b2,int now,bool sign)
152     {
153         int l = tree[now].l,r = tree[now].r,lc = tree[now].lc,rc = tree[now].rc,mid = (l + r) >> 1;
154         bool flag = false;
155         if (a1 == a2)    //处在同一行上
156         {
157             if (b1 == mid && b2 == mid + 1)
158                 tree[now].t[a1] = sign,flag = sign;
159             else if (b1 <= mid) modify(a1,b1,a2,b2,lc,sign);
160             else modify(a1,b1,a2,b2,rc,sign);
161         }
162         else             //处在同一列上
163         {
164             if (l == r) tree[now].u[1] = tree[now].u[2] = sign,flag = true;
165             else if (b1 <= mid) modify(a1,b1,a2,b2,lc,sign);
166             else modify(a1,b1,a2,b2,rc,sign);
167         }
168         updata(now,flag|sign);
169         return;
170     }
171 }seg;
172
173 inline int read()
174 {
175     int x=0,f=1; char ch=getchar();
176     while(ch<‘0‘||ch>‘9‘) { if(ch==‘-‘)f=-1; ch=getchar(); }
177     while(ch>=‘0‘&&ch<=‘9‘) { x=x*10+ch-‘0‘; ch=getchar(); }
178     return x * f;
179 }
180
181 int main()
182 {
183     freopen("1018.in","r",stdin);
184     freopen("1018.out","w",stdout);
185     n = read();
186     seg.build(1,n);
187     char opt[10]; int a1,a2,b1,b2;
188     do
189     {
190         scanf("%s ",opt);
191         if (opt[0] == ‘E‘) break;
192         a1 = read(); b1 = read(); a2 = read(); b2 = read();
193         if (b1 > b2) swap(a1,a2),swap(b1,b2);
194         if (opt[0] == ‘A‘)
195         {
196             if (seg.ask(a1,b1,a2,b2,1)) printf("Y\n");
197             else printf("N\n");
198         }
199         else if (opt[0] == ‘O‘) seg.modify(a1,b1,a2,b2,1,true);
200         else seg.modify(a1,b1,a2,b2,1,false);
201     }
202     while (true);
203     return 0;
204 }

时间: 2024-10-12 21:37:58

BZOJ 1018的相关文章

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

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

bzoj 1018 线段树维护连通性

本题将一道LCT的题特殊化(支持加边和删边,询问图的连通性),将图变成了2×m的网格图,然后就神奇地可以用线段树来维护. 对于每个区间[l,r],维护其四个角落之间的连通性(仅仅通过[l,r]这段的边构建起的连通性). 查询[l,r]时,先计算出[1,l-1],[l,r],[r+1,c]这三个线段的连通性,然后将[l,r]的四个角变成并查集的4个点,先用[l,r]中的6种关系更新,在看是否可以从左上角的点通过左边区间绕道左下角,以及从右上角通过右边区间绕道右下角,该并的并起来后直接看查询的点是否

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

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

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

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

bzoj 1018 堵塞的交通traffic

题外话 做了这个线段树的题我整个人都不好了,头一次做这种用线段树维护连通性的题,简直烦的要死= = Description 给你一个2*n的格子,开始全不联通,相邻两点可以连边,有3种操作 1:将(x1,y1),(x2,y2)变为连通 2:将(x1,y1),(x2,y2)变为不连通 3:询问(x1,y1),(x2,y2)是否联通 Soluion 用线段树维护6个信息,正常的4条边以及两条对角线是否联通,修改时用线段树维护 最蛋疼的是查询,比如[l,r]区间,不一定连通性只是在这个区间内的 比如虽

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 线段树维护图的连通性问题

思路: 我们可以搞一棵线段树 对于一段区间有6种情况需要讨论 左上右下.左上右上.左下右下.左下右上 这四种比较好维护 用左上右下举个例子吧 就是左儿子的左上右下&左区间到右区间下面有路&右儿子的左下右下 或者是左儿子的左上右上&左区间到右区间上面有路&右儿子的左上右下 还有两种  区间的左(右)端点上下能不能联通 需要维护 这种就是左儿子的上下连通或(左上右上&左上右下&左到右两条路都联通&右儿子的上下联通) (假设c1<c2) 最后要查的是