[bzoj2049][Sdoi2008]Cave 洞穴勘测——lct
Brief Description
给定一个森林,您需要支持两种操作:
- 链接两个节点。
- 断开两个节点之间的链接。
Algorithm Design
对于树上的操作,我们现在已经有了树链剖分可以处理这些问题。然而树链剖分不支持动态维护树上的拓扑结构。所以我们需要Link-Cut Tree(lct)来解决这种动态树问题。顺带一提的是,动态树也是Tarjan发明的。
首先我们介绍一个概念:Preferred path(实边),其他的边都是虚边。我们使用splay来实时地维护这条路径。
lct的核心操作是access。access操作可以把虚边变为实边,通过改变splay的拓扑结构来维护实边。
有了这个数据结构,我们依次来考虑两个操作。
对于链接两个节点,我们需要首先把x节点变为他所在树的根节点,然后直接令fa[x] = y即可。
怎样换根呢?稍微思考一下可以发现,我们直接把从根到他的路径反转即可。
对于第二种操作,我们直接断开拓扑关系即可。
另外实现的时候要注意,splay的根节点的父亲是他的上一个节点。所以zig和splay的写法应该格外注意。
Code
#include <algorithm>
#include <cctype>
#include <cstdio>
#include <stack>
using std::stack;
const int maxn = 10005;
inline int read() {
int x = 0, f = 1;
char ch = getchar();
while (!isdigit(ch)) {
if (ch == '-')
f = -1;
ch = getchar();
}
while (isdigit(ch)) {
x = x * 10 + ch - '0';
ch = getchar();
}
return x * f;
}
int n, m;
int fa[maxn], ch[maxn][2];
bool rev[maxn];
inline bool isroot(int x) { return ch[fa[x]][0] != x && ch[fa[x]][1] != x; }
void pushdown(int k) {
if (rev[k]) {
rev[k] = 0;
rev[ch[k][0]] ^= 1;
rev[ch[k][1]] ^= 1;
std::swap(ch[k][0], ch[k][1]);
}
}
void zig(int x) {
int y = fa[x], z = fa[y], l = (ch[y][1] == x), r = l ^ 1;
if (!isroot(y))
ch[z][ch[z][1] == y] = x;
fa[ch[y][l] = ch[x][r]] = y;
fa[ch[x][r] = y] = x;
fa[x] = z;
}
void splay(int x) {
stack<int> st;
st.push(x);
for (int i = x; !isroot(i); i = fa[i])
st.push(fa[i]);
while (!st.empty()) {
pushdown(st.top());
st.pop();
}
for (int y = fa[x]; !isroot(x); zig(x), y = fa[x])
if (!isroot(y))
zig((ch[fa[y]][0] == y) == (ch[y][0] == x) ? y : x);
}
void access(int x) {
int t = 0;
while (x) {
splay(x);
ch[x][1] = t;
t = x;
x = fa[x];
}
}
void rever(int x) {
access(x);
splay(x);
rev[x] ^= 1;
}
void link(int x, int y) {
rever(x);
fa[x] = y;
splay(x);
}
void cut(int x, int y) {
rever(x);
access(y);
splay(y);
ch[y][0] = fa[x] = 0;
}
int find(int x) {
access(x);
splay(x);
int y = x;
while (ch[y][0])
y = ch[y][0];
return y;
}
int main() {
#ifndef ONLINE_JUDGE
freopen("input", "r", stdin);
#endif
char ch[10];
int x, y;
n = read(), m = read();
for (int i = 1; i <= m; i++) {
scanf("%s", ch);
x = read();
y = read();
if (ch[0] == 'C')
link(x, y);
else if (ch[0] == 'D')
cut(x, y);
else {
if (find(x) == find(y))
printf("Yes\n");
else
printf("No\n");
}
}
}
[bzoj2049][Sdoi2008]Cave 洞穴勘测——lct的更多相关文章
- [BZOJ2049][Sdoi2008]Cave 洞穴勘测 LCT模板
2049: [Sdoi2008]Cave 洞穴勘测 Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 9705 Solved: 4674[Submit] ...
- [BZOJ2049] [SDOI2008] Cave 洞穴勘测 (LCT)
Description 辉辉热衷于洞穴勘测.某天,他按照地图来到了一片被标记为JSZX的洞穴群地区.经过初步勘测,辉辉发现这片区域由n个洞穴(分别编号为1到n)以及若干通道组成,并且每条通道连接了恰好 ...
- bzoj2049: [Sdoi2008]Cave 洞穴勘测 lct裸题
题意:三种操作一种摧毁一条边,一种链接一条边,一种查询两个点是否联通 题解:lct的link和cut即可 /********************************************** ...
- BZOJ2049 SDOI2008 Cave 洞穴勘测 【LCT】
BZOJ2049 SDOI2008 Cave 洞穴勘测 Description 辉辉热衷于洞穴勘测.某天,他按照地图来到了一片被标记为JSZX的洞穴群地区.经过初步勘测,辉辉发现这片区域由n个洞穴(分 ...
- 【LCT】BZOJ2049 [SDOI2008]Cave 洞穴勘测
2049: [Sdoi2008]Cave 洞穴勘测 Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 10059 Solved: 4863[Submit ...
- bzoj 2049: [Sdoi2008]Cave 洞穴勘测 (LCT)
链接:https://www.lydsy.com/JudgeOnline/problem.php?id=2049 题面: 2049: [Sdoi2008]Cave 洞穴勘测 Time Limit: 1 ...
- BZOJ 2049: [Sdoi2008]Cave 洞穴勘测 LCT
2049: [Sdoi2008]Cave 洞穴勘测 Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnli ...
- [bzoj2049][Sdoi2008]Cave 洞穴勘测_LCT
Cave 洞穴勘测 bzoj-2049 Sdoi-2008 题目大意:维护一个数据结构,支持森林中加边,删边,求两点连通性.n个点,m个操作. 注释:$1\le n\le 10^4$,$1\le m\ ...
- 【BZOJ2049】 [Sdoi2008]Cave 洞穴勘测 LCT/并查集
两种方法: 1.LCT 第一次LCT,只有link-cut和询问,无限T,到COGS上找了数据,发现splay里的父亲特判出错了(MD纸张),A了,好奇的删了反转T了.... #include < ...
随机推荐
- Hackerrank - [Algo] Matrix Rotation
https://www.hackerrank.com/challenges/matrix-rotation-algo 又是一道耗了两小时以上的题,做完了才想起来,这不就是几年前在POJ上做过的一个同类 ...
- 虚拟现实-VR-UE4-创建第一个C++项目——Hello word
这部分主要是调用在C++中用代码实现在游戏界面上面输出一行文字 第一步,新建C++版本的工程文件,在4.12版本以后,在创建后,都会自动打开Vs编译器. 如下图 在VS中点击编译,等带编译,第一次等待 ...
- 第十八篇 模块与包--time&random模块&模块导入import(os.path.dirname(os.path.abspath(__file__)))
模块 在Python中, 一个.py文件就称为一个模块. 使用模块的好处: 1. 最大的好处就是大大提高了代码的可维护性 2. 编写代码不必从零开始.一个模块编写完毕,就可以被其他地方引用.在写其他程 ...
- Ubuntu18.04 + CUDA9.0 + cuDNN7.3 + Tensorflow-gpu-1.12 + Jupyter Notebook深度学习环境配置
目录 一.Ubuntu18.04 LTS系统的安装 1. 安装文件下载 2. 制作U盘安装镜像文件 3. 开始安装 二.设置软件源的国内镜像 1. 设置方法 2.关于ubuntu镜像的小知识 三.Nv ...
- 利用calibre抓取新闻
Adding your favorite news website calibre has a powerful, flexible and easy-to-use framework for dow ...
- 【python】time 和datetime类型转换,字符串型变量转成日期型变量
s1='20120125'; 6 s2='20120216'; 7 a=time.strptime(s1,'%Y%m%d'); 8 b=time.strptime( ...
- jquery中ajax的使用(java)
AJAX方式 js:界面 var prjContextPath='<%=request.getContextPath()%>'; $(document).ready(function() ...
- P2127 序列排序
题目描述 小C有一个N个数的整数序列,这个序列的中的数两两不同.小C每次可以交换序列中的任意两个数,代价为这两个数之和.小C希望将整个序列升序排序,问小C需要的最小代价是多少? 输入输出格式 输入格式 ...
- 【转】The test form is only available for requests from the local machine 解决方法
描述:在内网可以访问 WebServer ,在外部网站无法通过IP调用 webserver 转自:http://www.cnblogs.com/xiaogelove/p/3447283.htm ...
- 如何快速的进行sql脚本升级
sql脚本升级即从一个老的脚本升级到一个新的全量的脚本.比如公司有某一个项目,有的客户已经用这个项目了,数据库里面去掉以前的初始化数据外,现在还有了客户自己的数据.但是这个版本中有严重的bug,所以为 ...