SPOJ OTOCI 动态树 LCT
裸的动态树问题。
回顾一下我们对树的认识。
最初,它是一个连通的无向的无环的图,然后我们发现由一个根出发进行BFS 会出现层次分明的树状图形。
然后根据树的递归和层次性质,我们得到了很多有趣的算法,比如单源最短路等等。
如今,我们面对更复杂的问题,给定一个森林,随时更改树的形态,并询问两个节点之间路径上所有点的权值和。
要求复杂度O(Logn)
我们把树看作由若干条链构成,每个链用一个splay维护。
至此,我们对树的认识已经到了一个比较高的水平了。
关于LCT的详细阐述,参考http://www.cnblogs.com/zinthos/p/3900225.html
代码并不复杂, 一句话 splay的核心是splay(x) LCT的核心是access(x)
此处join(x,y)通过对x的翻转实现,splay(x)后,反转x x就由队尾变成队首此时PNT(x)==null, PNT(x)=y就实现了连接(x,y).
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm> using namespace std; const int MaxNode=31000; int Lch[MaxNode];
int Rch[MaxNode];
int Pnt[MaxNode];
int Data[MaxNode];
int Sum[MaxNode];
int Rev[MaxNode];
int List[MaxNode];
int Total; inline bool isRoot(int t){
return (!Pnt[t]||(Lch[Pnt[t]]!=t&&Rch[Pnt[t]]!=t));
}
inline void Update(int cur){
Sum[cur]=Sum[Lch[cur]]+Sum[Rch[cur]]+Data[cur];
}
void Reverse(int cur){
if (!Rev[cur]) return;
swap(Lch[cur],Rch[cur]);
Rev[Lch[cur]]^=1;
Rev[Rch[cur]]^=1;
Rev[cur]=0;
}
void LeftRotate(int cur){
if (isRoot(cur)) return;
int pnt=Pnt[cur],anc=Pnt[pnt];
Lch[pnt]=Rch[cur];
if (Rch[cur]) Pnt[Rch[cur]]=pnt;
Rch[cur]=pnt;
Pnt[pnt]=cur;
Pnt[cur]=anc;
if (anc){
if (Lch[anc]==pnt) Lch[anc]=cur;
else if (Rch[anc]==pnt) Rch[anc]=cur;
}
Update(pnt);
Update(cur);
}
void RightRotate(int cur){
if (isRoot(cur)) return;
int pnt=Pnt[cur],anc=Pnt[pnt];
Rch[pnt]=Lch[cur];
if (Lch[cur]) Pnt[Lch[cur]]=pnt;
Lch[cur]=pnt;
Pnt[pnt]=cur;
Pnt[cur]=anc;
if (anc){
if (Rch[anc]==pnt) Rch[anc]=cur;
else if (Lch[anc]==pnt) Lch[anc]=cur;
}
Update(pnt);
Update(cur);
}
void Splay(int cur){
int pnt,anc;
List[++Total]=cur;
for (int i=cur;!isRoot(i);i=Pnt[i]) List[++Total]=Pnt[i];
for (;Total;--Total)
if (Rev[List[Total]]) Reverse(List[Total]);
while (!isRoot(cur)){
pnt=Pnt[cur];
if (isRoot(pnt)){// 父亲是根结点,做一次旋转
if (Lch[pnt]==cur) LeftRotate(cur);
else RightRotate(cur);
}
else{
anc=Pnt[pnt];
if (Lch[anc]==pnt){
if (Lch[pnt]==cur) LeftRotate(pnt),LeftRotate(cur);// 一条线
else RightRotate(cur),LeftRotate(cur);// 相反两次
}
else{
if (Rch[pnt]==cur) RightRotate(pnt),RightRotate(cur);// 一条线
else LeftRotate(cur),RightRotate(cur);// 相反两次
}
}
}
}
int Expose(int u){
int v=0;
for (;u;u=Pnt[u]) Splay(u),Rch[u]=v,v=u,Update(u);
for (;Lch[v];v=Lch[v]);
return v;
}
void Modify(int x,int d){
Splay(x);
Data[x]=d;
Update(x);
}
int Query(int x,int y){
int rx=Expose(x),ry=Expose(y);
if (rx==ry){
for (int u=x,v=0;u;u=Pnt[u]){
Splay(u);
if (!Pnt[u]) return Sum[Rch[u]]+Data[u]+Sum[v];
Rch[u]=v;
Update(u);
v=u;
}
}
return -1;
}
bool Join(int x,int y){
int rx=Expose(x),ry=Expose(y);
if (rx==ry) return false;
else{
Splay(x);
Rch[x]=0;
Rev[x]=1;
Pnt[x]=y;
Update(x);
return true;
}
}
void Cut(int x){
if (Pnt[x]){
Expose(x);
Pnt[Lch[x]]=0;
Lch[x]=0;
Update(x);
}
}
int n,Q; void init(){
Total=0;
memset(Rev,0,sizeof(Rev));
memset(Pnt,0,sizeof(Pnt));
memset(Lch,0,sizeof(Lch));
memset(Rch,0,sizeof(Rch));
memset(Sum,0,sizeof(Sum));
}
char cmd[22];
int main()
{
init();
scanf("%d",&n);
for (int i=1;i<=n;i++) scanf("%d",&Data[i]);
scanf("%d",&Q);
while (Q--){
int x,y;
scanf("%s%d%d",cmd,&x,&y);
if (cmd[0]=='p'){
Modify(x,y);
}
if (cmd[0]=='b'){
if (Join(x,y)) printf("yes\n");
else printf("no\n");
}
if (cmd[0]=='e'){
int ans=Query(x,y);
if (ans==-1) printf("impossible\n");
else printf("%d\n",ans);
}
}
return 0;
}
SPOJ OTOCI 动态树 LCT的更多相关文章
- hdu 5398 动态树LCT
GCD Tree Time Limit: 5000/2500 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Su ...
- hdu 5002 (动态树lct)
Tree Time Limit: 16000/8000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submi ...
- 动态树LCT小结
最开始看动态树不知道找了多少资料,总感觉不能完全理解.但其实理解了就是那么一回事...动态树在某种意思上来说跟树链剖分很相似,都是为了解决序列问题,树链剖分由于树的形态是不变的,所以可以通过预处理节点 ...
- bzoj2049-洞穴勘测(动态树lct模板题)
Description 辉辉热衷于洞穴勘测.某天,他按照地图来到了一片被标记为JSZX的洞穴群地区.经过初步勘测,辉辉发现这片区域由n个洞穴(分别编号为1到n)以及若干通道组成,并且每条通道连接了恰好 ...
- [模板] 动态树/LCT
简介 LCT是一种数据结构, 可以维护树的动态加边, 删边, 维护链上信息(满足结合律), 单次操作时间复杂度 \(O(\log n)\).(不会证) 思想类似树链剖分, 因为splay可以换根, 用 ...
- 动态树LCT(Link-cut-tree)总结+模板题+各种题目
一.理解LCT的工作原理 先看一道例题: 让你维护一棵给定的树,需要支持下面两种操作: Change x val: 令x点的点权变为val Query x y: 计算x,y之间的唯一的最短路径的点 ...
- 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 ...
- BZOJ 2002: [Hnoi2010]Bounce 弹飞绵羊 (动态树LCT)
2002: [Hnoi2010]Bounce 弹飞绵羊 Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 2843 Solved: 1519[Submi ...
- HDU 5002 Tree(动态树LCT)(2014 ACM/ICPC Asia Regional Anshan Online)
Problem Description You are given a tree with N nodes which are numbered by integers 1..N. Each node ...
随机推荐
- python第一章计算机基础
第一章 计算机基础 1.1 硬件 计算机基本的硬件由:CPU / 内存 / 主板 / 硬盘 / 网卡 / 显卡 / 显示器 等组成,只有硬件但硬件之间无法进行交流和通信. 1.2 操作系统 操作系统用 ...
- PAT 1059. C语言竞赛
PAT 1059. C语言竞赛 C语言竞赛是浙江大学计算机学院主持的一个欢乐的竞赛.既然竞赛主旨是为了好玩,颁奖规则也就制定得很滑稽: 冠军将赢得一份"神秘大奖"(比如很巨大的一本 ...
- 19-看图理解数据结构与算法系列(Radix树)
Radix树 Radix树,即基数树,也称压缩前缀树,是一种提供key-value存储查找的数据结构.与Trie不同的是,它对Trie树进行了空间优化,只有一个子节点的中间节点将被压缩.同样的,Rad ...
- Notepad++ 连接远程 FTP 进行文件编辑
一.下载安装 Notepad++ 1.下载 Notepad++ : https://pan.baidu.com/s/1o7VrS4y 密码 : ck8a 2.安装 Notepad++ 2.1.勾选所有 ...
- Webdriver测试脚本1(打开网页并打印标题)
案例: 启动火狐浏览器 首页打开博客园页面,打印网页标题,等待3秒 打开百度首页,打印网页标题,再等待2秒 关闭浏览器 from selenium import webdriver from time ...
- 【裸的并查集】POJ 1611 The Suspects
http://poj.org/problem?id=1611 [Accepted] #include<iostream> #include<cstdio> #include&l ...
- hdu 3943 经典数位dp好题
/* 题意:求出p-q的第j个nya数 数位dp,求出p-q的所有nya数的个数很好求,但是询问求出最终那个第j个值时是我不会求了看了下别人的思路 具体就是把p-q的第j个转化成0-q的第low+j个 ...
- android开发里跳过的坑-AS导入NDK工程提示错误 No such property: sdkHandler for class: com.android.build.gradle.LibraryPlugin
接到一个NDK工程需要调试,导入后发现总是提示错误 Error:(37, 1) A problem occurred evaluating project ':libuvccamera'.> N ...
- POJ 2240_Arbitrage
题意: 给定一系列货币汇率,求能否从一种货币,经过一系列转换,最终转化回更高价值的该种货币. 分析: 即为求最长路并判断是否存在"正"权值回路,这里用的bellmanford算法. ...
- Centos6.4安装Zimbra初步教程
环境: 1.centos6.4*64位版本 2.主机最好内存设置在2G以上,要不安装的时候卡死你 3.下载最新的开源的Zimbra安装包,下载zcs-8.0.4_GA_5737.RHEL6_64.20 ...