[BZOJ 1018] [SHOI2008] 堵塞的交通traffic 【线段树维护联通性】
题目链接:BZOJ - 1018
题目分析
这道题就说明了刷题少,比赛就容易跪..SDOI Round1 Day2 T3 就是与这道题类似的..然而我并没有做过这道题..
这道题是线段树维护联通性的经典模型。
我们线段树的一个节点表示一个区间的联通性,有 6 个 bool 值,表示这个区间的 4 个角上的点之间的联通性。
然后用两个子区间的联通性和两个子区间之间的连边情况合并出整个区间的联通性。
修改某条边时,先在边的数组中修改,然后从这条边所在的点的线段树叶子开始向上 Update 。
询问两点之间的联通性时,假如它们的列分别是 y1, y2, 那么我们要求出 [1, y1] [y1, y2] [y2, n] 的联通性。
然后用这三个联通性组合起来手动枚举各种情况判断两个点是否联通。
因为分别处于 y1, y2 的两个点,之间可能不只是通过 [y1, y2] 之间的边联通,而是需要用到两侧的边连接起来。
代码
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm> using namespace std; inline int gmin(int a, int b) {return a < b ? a : b;}
inline int gmax(int a, int b) {return a > b ? a : b;} const int MaxN = 100000 + 5; int n; char Str[15]; bool A[MaxN][3]; struct ES
{
bool a1, a2, b1, b2, c1, c2;
} T[MaxN * 4]; inline ES Plus(ES e1, ES e2, int m)
{
ES ret;
ret.a1 = e1.a1 || (e1.b1 && e1.b2 && A[m][1] && A[m][2] && e2.a1);
ret.a2 = e2.a2 || (e2.b1 && e2.b2 && A[m][1] && A[m][2] && e1.a2);
ret.b1 = (e1.b1 && A[m][1] && e2.b1) || (e1.c1 && A[m][2] && e2.c2);
ret.b2 = (e1.b2 && A[m][2] && e2.b2) || (e1.c2 && A[m][1] && e2.c1);
ret.c1 = (e1.b1 && A[m][1] && e2.c1) || (e1.c1 && A[m][2] && e2.b2);
ret.c2 = (e1.b2 && A[m][2] && e2.c2) || (e1.c2 && A[m][1] && e2.b1);
return ret;
} void Build(int x, int s, int t)
{
if (s == t)
{
T[x].a1 = T[x].a2 = T[x].c1 = T[x].c2 = false;
T[x].b1 = T[x].b2 = true;
return;
}
int m = (s + t) >> 1;
Build(x << 1, s, m);
Build(x << 1 | 1, m + 1, t);
T[x] = Plus(T[x << 1], T[x << 1 | 1], m);
} void Modify(int x, int s, int t, int Pos)
{
if (s == t)
{
T[x].a1 = T[x].a2 = T[x].c1 = T[x].c2 = A[Pos][0];
T[x].b1 = T[x].b2 = true;
return;
}
int m = (s + t) >> 1;
if (Pos <= m) Modify(x << 1, s, m, Pos);
else Modify(x << 1 | 1, m + 1, t, Pos);
T[x] = Plus(T[x << 1], T[x << 1 | 1], m);
} ES Get(int x, int s, int t, int l, int r)
{
if (l <= s && r >= t) return T[x];
ES ret;
int m = (s + t) >> 1;
if (r <= m) ret = Get(x << 1, s, m, l, r);
else if (l >= m + 1) ret = Get(x << 1 | 1, m + 1, t, l, r);
else ret = Plus(Get(x << 1, s, m, l, r), Get(x << 1 | 1, m + 1, t, l, r), m);
return ret;
} int main()
{
scanf("%d", &n);
int x, y, xx, yy;
bool f, Ans;
ES El, Ex, Er;
Build(1, 1, n);
while (true)
{
scanf("%s", Str);
if (strcmp(Str, "Exit") == 0) break;
scanf("%d%d%d%d", &x, &y, &xx, &yy);
if (strcmp(Str, "Ask") == 0)
{
if (y > yy)
{
swap(x, xx);
swap(y, yy);
}
El = Get(1, 1, n, 1, y);
Ex = Get(1, 1, n, y, yy);
Er = Get(1, 1, n, yy, n);
if (x == xx)
{
if (x == 1)
Ans = Ex.b1 || \
(A[y - 1][1] && A[y - 1][2] && El.a2 && Ex.c2) || \
(A[yy][1] && A[yy][2] && Er.a1 && Ex.c1) || \
(A[y - 1][1] && A[y - 1][2] && El.a2 && A[yy][1] && A[yy][2] && Er.a1 && Ex.b2);
else
Ans = Ex.b2 || \
(A[y - 1][1] && A[y - 1][2] && El.a2 && Ex.c1) || \
(A[yy][1] && A[yy][2] && Er.a1 && Ex.c2) || \
(A[y - 1][1] && A[y - 1][2] && El.a2 && A[yy][1] && A[yy][2] && Er.a1 && Ex.b1);
}
else
{
if (x < xx)
Ans = Ex.c1 || \
(A[y - 1][1] && A[y - 1][2] && El.a2 && Ex.b2) || \
(Ex.b1 && A[yy][1] && A[yy][2] && Er.a1);
else
Ans = Ex.c2 || \
(A[y - 1][1] && A[y - 1][2] && El.a2 && Ex.b1) || \
(Ex.b2 && A[yy][1] && A[yy][2] && Er.a1);
}
if (Ans) printf("Y\n");
else printf("N\n");
}
else
{
if (strcmp(Str, "Open") == 0) f = true;
else f = false;
if (x == xx)
{
A[gmin(y, yy)][x] = f;
Modify(1, 1, n, gmin(y, yy));
}
else
{
A[y][0] = f;
Modify(1, 1, n, y);
}
}
}
return 0;
}
[BZOJ 1018] [SHOI2008] 堵塞的交通traffic 【线段树维护联通性】的更多相关文章
- BZOJ 1018: [SHOI2008]堵塞的交通traffic [线段树 区间信息]
1018: [SHOI2008]堵塞的交通traffic Time Limit: 3 Sec Memory Limit: 162 MBSubmit: 3064 Solved: 1027[Submi ...
- BZOJ 1018: [SHOI2008]堵塞的交通traffic(线段树分治+并查集)
传送门 解题思路 可以离线,然后确定每个边的出现时间,算这个排序即可.然后就可以线段树分治了,连通性用并查集维护,因为要撤销,所以要按秩合并,时间复杂度\(O(nlog^2 n)\) 代码 #incl ...
- [SHOI2008]堵塞的交通(线段树维护联通性)
题目 2行c列个点,开始时互不联通,支持给同一列或着同一行相邻的两个点连边,和询问两个点能否在一个联通块里. 1≤C≤100000 1<=操作数<=100000; 题解 线段树的又一个骚操 ...
- [BZOJ1018][SHOI2008]堵塞的交通traffic 线段树维护连通性
1018: [SHOI2008]堵塞的交通traffic Time Limit: 3 Sec Memory Limit: 162 MB Submit: 3795 Solved: 1253 [Sub ...
- 数据结构(线段树):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 线段树
[BZOJ1018][SHOI2008]堵塞的交通traffic Description 有一天,由于某种穿越现象作用,你来到了传说中的小人国.小人国的布局非常奇特,整个国家的交通系统可以被看成是一个 ...
- 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部分:两点左边. ...
随机推荐
- Android注解支持(Support Annotations)
注解支持(Support Annotations) Android support library从19.1版本开始引入了一个新的注解库,它包含很多有用的元注解,你能用它们修饰你的代码,帮助你发现bu ...
- HDU 1576 A/B 扩展欧几里德算法
A/B Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submis ...
- Java经典封装JDBC模板(充分体现面向对象思想)(转)
程序清单一览 bean类 package com.software.usermanager.bean; public class Users { private String id; private ...
- spring入门之helloworld
1.第一个spring例子 1.建立工程 建立一个java project就可以. 导包,helloworld包括下面两个最少的包: 到http://www.springsource.org/down ...
- javascript如何列出全局对象的非原生属性。
Why 研究一个网站前端技术的时候,了解它的全局的对象是一个好的入口, 一般来说,常见的库就会用外观模式,最后暴露一个对象给用户调用, 比如jQuery,requirejs,angular,react ...
- IHttpModule实现URL重写
1.用自定义IHttpModule实现URL重写 一般来说,要显示一些动态数据总是采用带参数的方式,比如制作一个UserInfo.aspx的动态页面用于显示系统的UserInfo这个用户信息表的数据, ...
- build/envsetup.sh内lunch解析
........ # 测试device是否存在且是一个目录 并且 只查找device目录4层以上的子目录,名字为vendorsetup.sh 并且 将命令执行的错误报告直接送往回收站 不显示在屏幕上 ...
- 开源 android
Android经典的开源项目其实非常多,但是国内的博客总是拿着N年前的一篇复制来复制去,实在是不利于新手学习.今天爬爬把自己熟悉的一些开源项目整理起来,希望能对Android开发同学们有所帮助.另外, ...
- JS 自定义回调函数callback
1 应用场景:js的异步加载,在get,post,ajax异步加载的时候,可能对应的请求没有完成,这时需要使用请求回来的数据作为参数调用其他函数,这时就需要使用回调函数. 2 回调函数作用:等待函数调 ...
- RABBITMQ安装注意点
关于 RABBITMQ的配置问题安装问题windows7 和window 10我都试了windows10安装和配置不要出现中文和空格,不然你日寒飞的心都有了ERLANG的安装也是Win7直接默认的路径 ...