[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部分:两点左边. ...
随机推荐
- BZOJ 2754([SCOI2012]喵喵叫的星球-统计序列的后缀阵列中子序列出现次数)
2754: [SCOI2012]喵喵叫的星球 Time Limit: 20 Sec Memory Limit: 128 MB Submit: 805 Solved: 380 [id=2754&qu ...
- Java数据库连接代码集合(转)
Java数据库连接接口(JDBC)是Java里定义的一套用于数据库连接和操作的API的集合.有不同的数据库厂商提供这套接口的实现类,对于 Java程序员来说,程序员不需要关心数据库的底层的实现,统一的 ...
- JAVA对象之生
https://yq.aliyun.com/users/1556056716932876?spm=5176.100239.blogrightarea55811.3.6cvyJd
- mysql 交互式连接和非交互式连接
交互式客户端定义为在mysql_real_connect()中使用CLIENT_INTERACTIVE选项的客户端 mysql_real_connect() 函数介绍 函数原型描述: MYSQL *m ...
- linux 进程综合指令
1. 查询当前机器运行的进程总数: ps -ef | wc -l ps -ef | grep httpd | wc -l 2. ulimit命令 表 1. ulimit 参数说明 选项 [option ...
- Day05 - Python 常用模块
1. 模块简介 模块就是一个保存了 Python 代码的文件.模块能定义函数,类和变量.模块里也能包含可执行的代码. 模块也是 Python 对象,具有随机的名字属性用来绑定或引用. 下例是个简单的模 ...
- android打包签名介绍
Keytool 是一个有效的安全钥匙和证书的管理工具. Java 中的 keytool.exe (位于 JDK\Bin 目录下)可以用来创建数字证书,所有的数字证书是以一条一条(采用别名区别)的形式存 ...
- Customize the SharePoint 2013 search experience with a Content Enrichment web service
Did you ever wish you had more control over how your content is indexed and presented as search resu ...
- sql Server 触发器 调用java.
在这里,通过 xp_cmdshell 调用java程序. 步骤: 1)开启 xp_cmdshell(sql Server 2008): 通过如下命令开启: -- To allow advanced o ...
- virtualbox共享文件夹无访问权限问题解决方法
virtualbox共享文件夹无访问权限问题解决方法 早就困扰了,这次新装虚拟机又碰到了,记录下来. 这篇文章主要介绍了virtualbox共享文件夹无访问权限问题解决方法,造成这个问题的原因是不跟v ...