bzoj2049-洞穴勘测(动态树lct模板题)
Description
辉辉热衷于洞穴勘测。某天,他按照地图来到了一片被标记为JSZX的洞穴群地区。经过初步勘测,辉辉发现这片区域由n个洞穴(分别编号为1到n)以及若干通道组成,并且每条通道连接了恰好两个洞穴。假如两个洞穴可以通过一条或者多条通道按一定顺序连接起来,那么这两个洞穴就是连通的,按顺序连接在一起的这些通道则被称之为这两个洞穴之间的一条路径。洞穴都十分坚固无法破坏,然而通道不太稳定,时常因为外界影响而发生改变,比如,根据有关仪器的监测结果,123号洞穴和127号洞穴之间有时会出现一条通道,有时这条通道又会因为某种稀奇古怪的原因被毁。辉辉有一台监测仪器可以实时将通道的每一次改变状况在辉辉手边的终端机上显示:如果监测到洞穴u和洞穴v之间出现了一条通道,终端机上会显示一条指令 Connect u v 如果监测到洞穴u和洞穴v之间的通道被毁,终端机上会显示一条指令 Destroy u v 经过长期的艰苦卓绝的手工推算,辉辉发现一个奇怪的现象:无论通道怎么改变,任意时刻任意两个洞穴之间至多只有一条路径。因而,辉辉坚信这是由于某种本质规律的支配导致的。因而,辉辉更加夜以继日地坚守在终端机之前,试图通过通道的改变情况来研究这条本质规律。然而,终于有一天,辉辉在堆积成山的演算纸中崩溃了……他把终端机往地面一砸(终端机也足够坚固无法破坏),转而求助于你,说道:“你老兄把这程序写写吧”。辉辉希望能随时通过终端机发出指令 Query u v,向监测仪询问此时洞穴u和洞穴v是否连通。现在你要为他编写程序回答每一次询问。已知在第一条指令显示之前,JSZX洞穴群中没有任何通道存在。
Input
第一行为两个正整数n和m,分别表示洞穴的个数和终端机上出现过的指令的个数。以下m行,依次表示终端机上出现的各条指令。每行开头是一个表示指令种类的字符串s("Connect”、”Destroy”或者”Query”,区分大小写),之后有两个整数u和v (1≤u, v≤n且u≠v) 分别表示两个洞穴的编号。
Output
对每个Query指令,输出洞穴u和洞穴v是否互相连通:是输出”Yes”,否则输出”No”。(不含双引号)
Sample Input
200 5
Query 123 127
Connect 123 127
Query 123 127
Destroy 127 123
Query 123 127
样例输入2 cave.in
3 5
Connect 1 2
Connect 3 1
Query 2 3
Destroy 1 3
Query 2 3
Sample Output
No
Yes
No
样例输出2 cave.out
Yes
No
题意: 有三种操作,建边,毁边以及查询两个点是否相通,保证任意两个点之间最多只有一条相通的路径,也就是说整个图总是树或森林。
解析: 动态树模板题,另附两个介绍动态树的网址:
https://oi.abcdabcd987.com/summary-of-link-cut-tree/
http://wenku.baidu.com/view/75906f160b4e767f5acfcedb.html
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=;
struct lct
{
lct *fa,*son[];
int rev;
void pushdown() //把延迟更新的标记清除掉
{
if(!rev) return;
swap(son[],son[]); //翻转,交换左右儿子
son[]->rev^=; son[]->rev^=;
rev=;
}
};
struct LCT
{
lct data[maxn];
lct *null;
void init(int Size=maxn-) //初始化
{
null=data; //null指向首元素
for(int i=;i<=Size;i++)
data[i].son[]=data[i].son[]=data[i].fa=null;
}
bool Same(lct* x,lct* &y) //判断x和x的父亲是否在同一树里
{
return (y=x->fa)!=null&&(y->son[]==x||y->son[]==x);
}
void Rotate(lct* x,int d) //翻转
{
lct* y=x->fa; //x的父亲
y->son[d^]=x->son[d];
if(x->son[d]!=null) x->son[d]->fa=y; //x的子节点的父亲指向y
x->fa=y->fa; //连接
if(y->fa->son[]==y) x->fa->son[]=x;
else if(y->fa->son[]==y) x->fa->son[]=x;
x->son[d]=y;
y->fa=x;
}
void Splay(lct* x)
{
x->pushdown(); //清除标记
lct* y;
while(Same(x,y)) //没有到树的最顶点
{
y->pushdown();
x->pushdown();
Rotate(x,y->son[]==x); //翻转
}
}
lct* Access(lct* u) //打通路径
{
lct *v=null;
for(;u!=null;u=u->fa)
{
Splay(u);
u->son[]=v;
v=u;
}
return v;
}
lct* GetRoot(lct* x) //得到根
{
for(x=Access(x);x->pushdown(),x->son[]!=null;x=x->son[]);
return x;
}
void MakeRoot(lct* x) //使x成为根
{
Access(x)->rev^=;
Splay(x);
}
void Link(lct* x,lct* y) //连接两个点
{
MakeRoot(x);
x->fa=y;
Access(x);
}
void Cut(lct* x,lct* y) //断开两个点
{
MakeRoot(x);
Access(y);
Splay(y);
y->son[]->fa=null;
y->son[]=null;
}
}A;
int N,M;
int main()
{
scanf("%d%d",&N,&M);
A.init(N);
int x,y;
char S[];
while(M--)
{
scanf("%s%d%d",S,&x,&y);
if(S[]=='Q')
{
lct *a=A.GetRoot(A.data+x);
lct *b=A.GetRoot(A.data+y);
if(a!=A.null&&a==b) printf("Yes\n");
else printf("No\n");
}
else if(S[]=='D') A.Cut(A.data+x,A.data+y);
else A.Link(A.data+x,A.data+y);
}
return ;
}
bzoj2049-洞穴勘测(动态树lct模板题)的更多相关文章
- BZOJ-2049 Cave洞穴勘测 动态树Link-Cut-Tree (并查集骗分TAT)
2049: [Sdoi2008]Cave 洞穴勘测 Time Limit: 10 Sec Memory Limit: 259 MB Submit: 5833 Solved: 2666 [Submit] ...
- bzoj 2049: [Sdoi2008]Cave 洞穴勘测 动态树
2049: [Sdoi2008]Cave 洞穴勘测 Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 3119 Solved: 1399[Submit] ...
- hdu 5002 (动态树lct)
Tree Time Limit: 16000/8000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submi ...
- hdu 5398 动态树LCT
GCD Tree Time Limit: 5000/2500 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Su ...
- HDU 4718 The LCIS on the Tree (动态树LCT)
The LCIS on the Tree Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Oth ...
- 动态树LCT(Link-cut-tree)总结+模板题+各种题目
一.理解LCT的工作原理 先看一道例题: 让你维护一棵给定的树,需要支持下面两种操作: Change x val: 令x点的点权变为val Query x y: 计算x,y之间的唯一的最短路径的点 ...
- 算法复习——LCT(bzoj2049洞穴勘测)
题目: Description 辉辉热衷于洞穴勘测.某天,他按照地图来到了一片被标记为JSZX的洞穴群地区.经过初步勘测,辉辉发现这片区域由n个洞穴(分别编号为1到n)以及若干通道组成,并且每条通道连 ...
- [模板] 动态树/LCT
简介 LCT是一种数据结构, 可以维护树的动态加边, 删边, 维护链上信息(满足结合律), 单次操作时间复杂度 \(O(\log n)\).(不会证) 思想类似树链剖分, 因为splay可以换根, 用 ...
- 动态树LCT小结
最开始看动态树不知道找了多少资料,总感觉不能完全理解.但其实理解了就是那么一回事...动态树在某种意思上来说跟树链剖分很相似,都是为了解决序列问题,树链剖分由于树的形态是不变的,所以可以通过预处理节点 ...
随机推荐
- maven编写主代码与测试代码
3.2 编写主代码 项目主代码和测试代码不同,项目的主代码会被打包到最终的构件中(比如jar),而测试代码只在运行测试时用到,不会被打包.默认情况下,Maven假设项目主代码位于src/main/ja ...
- adb网络调试
对Android比较熟悉的开发人员,对adb通过USB(USB连接Android设备)调试Android设备应该不会陌生,因为大部分资料都是这样做的.但是假如你的Android设备没有USB口,只有网 ...
- pyqt cvs保存
# -*- coding: utf-8 -*-__author__ = 'Administrator'import sys, csvfrom PyQt4 import QtGui, QtCore cl ...
- Java 学习第一天
java 学习路线 http://edu.csdn.net/main/studyline/heimaline.html?flz java 学习视频 —— 马士兵:毕向东
- vmware下给linux添加硬盘
http://blog.csdn.net/robbie1314520/archive/2010/08/10/5802724.aspx 创建虚拟硬盘 1.关闭VM中正在运行的虚拟系统: 2.EDIT V ...
- [转]iOS hybrid App 的实现原理及性能监测
转自:http://www.cocoachina.com/ios/20151118/14270.html iOS hybrid App 的实现原理及性能监测 2015-11-18 11:39 编辑: ...
- 搭建LAMP架构
1. 为什么下载源码包需要到官网上去下载?简单说就是为了安全,如果是非官方下载的源码包,有可能被别有用心的人动过手脚. 2. 64位机器是否可以安装32位rpm包?64位机器是否可以安装32位的mys ...
- CPU使用率和Load Average的关系
看了几篇博客总结的区别,自己终于明白了含义,在这里将理解总结一下: 对于定义和解释,感觉淘测试上的更容易理解: 引用如下: CPU使用率: 一段时间内CPU的使用状况,从这个指标可以看出某一段时间内 ...
- 通过maven创建自己的archetype
最近项目组做好一套框架,为了推广需要创建一些空白项目给项目组使用,因为所有的空白项目里面的配置基本上都是一样的,为了减少重复工作,想通过maven创建一个自己的archetype,于是在网上大致搜了一 ...
- oracle数据库事务相关【weber出品必属精品】
事务的概念:事务:一个事务由一组构成一个逻辑操作的DML语句组成 事务有开始有结束,事务以DML语句开始,以Conmmit和Rollback结束.以下情况会使得事务结束: 1. 执行COMMIT 或者 ...