考虑\(LCT\)

不难发现,我们不需要换根...

对于操作\(1\),\(splay(u)\)然后连虚边即可

对于操作\(3\),我们可以先\(access(u)\),然后再\(access(v)\),然后查最后一个虚边变实边的点

对于操作\(2\)

可以选择\(access(u), splay(u)\),然后从\(u\)所在的\(splay\)中删去\(u\)点

也可以选择\(access(u), access(v), splay(u)\),这时,边\((u, v)\)成为虚边,十分好删除

复杂度\(O(n \log n)\)


版本1:

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std; #define ri register int
#define rep(io, st, ed) for(ri io = st; io <= ed; io ++)
#define drep(io, ed, st) for(ri io = ed; io >= st; io --) #define gc getchar
inline int read() {
int p = 0, w = 1; char c = gc();
while(c > '9' || c < '0') { if(c == '-') w = -1; c = gc(); }
while(c >= '0' && c <= '9') p = p * 10 + c - '0', c = gc();
return p * w;
} const int sid = 1e5 + 5; int n, m;
char s[sid];
int son[sid][2], fa[sid], pra[sid]; #define ls(o) son[(o)][0]
#define rs(o) son[(o)][1] inline bool isrc(int o) { return rs(fa[o]) == o; }
inline bool isr(int o) { return !fa[o] || (ls(fa[o]) != o && rs(fa[o]) != o); } inline void rotate(int o) {
int f = fa[o], g = fa[f];
int ro = isrc(o), rf = isrc(f), p = son[o][ro ^ 1];
if(!isr(f)) son[g][rf] = o; son[o][ro ^ 1] = f; son[f][ro] = p;
fa[p] = f; fa[f] = o; fa[o] = g;
} inline void splay(int o) {
while(!isr(o)) {
int f = fa[o];
if(!isr(f)) rotate(isrc(f) == isrc(o) ? f : o);
rotate(o);
}
} int lca = 0;
inline void access(int o) {
int lst = 0;
while(o) {
splay(o); rs(o) = lst;
lca = lst = o; o = fa[o];
}
} int main() {
n = read(); m = read();
rep(i, 1, m) {
int u, v;
scanf("%s", s);
if(s[1] == 'i') {
u = read(); v = read();
splay(u); pra[u] = v; fa[u] = v;
}
else if(s[1] == 'c') {
u = read(); v = read();
access(u); access(v);
printf("%d\n", lca);
}
else if(s[1] == 'u') {
u = read();
access(u); access(pra[u]);
splay(u); fa[u] = 0;
}
}
return 0;
}

版本\(2\):

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std; #define ri register int
#define rep(io, st, ed) for(ri io = st; io <= ed; io ++)
#define drep(io, ed, st) for(ri io = ed; io >= st; io --) #define gc getchar
inline int read() {
int p = 0, w = 1; char c = gc();
while(c > '9' || c < '0') { if(c == '-') w = -1; c = gc(); }
while(c >= '0' && c <= '9') p = p * 10 + c - '0', c = gc();
return p * w;
} const int sid = 1e5 + 5; int n, m;
char s[sid];
int son[sid][2], fa[sid], pra[sid]; #define ls(o) son[(o)][0]
#define rs(o) son[(o)][1] inline bool isrc(int o) { return rs(fa[o]) == o; }
inline bool isr(int o) { return !fa[o] || (ls(fa[o]) != o && rs(fa[o]) != o); } inline void rotate(int o) {
int f = fa[o], g = fa[f];
int ro = isrc(o), rf = isrc(f), p = son[o][ro ^ 1];
if(!isr(f)) son[g][rf] = o; son[o][ro ^ 1] = f; son[f][ro] = p;
fa[p] = f; fa[f] = o; fa[o] = g;
} inline void splay(int o) {
while(!isr(o)) {
int f = fa[o];
if(!isr(f)) rotate(isrc(f) == isrc(o) ? f : o);
rotate(o);
}
} int lca = 0;
inline void access(int o) {
int lst = 0;
while(o) {
splay(o); rs(o) = lst;
lca = lst = o; o = fa[o];
}
} int main() {
n = read(); m = read();
rep(i, 1, m) {
int u, v;
scanf("%s", s);
if(s[1] == 'i') {
u = read(); v = read();
splay(u); pra[u] = v; fa[u] = v;
}
else if(s[1] == 'c') {
u = read(); v = read();
access(u); access(v);
printf("%d\n", lca);
}
else if(s[1] == 'u') {
u = read();
access(u); splay(u);
ls(u) = fa[ls(u)] = 0;
}
}
return 0;
}

SPOJ8791 DYNALCA LCT的更多相关文章

  1. spoj DYNALCA - Dynamic LCA

    http://www.spoj.com/problems/DYNALCA/ 此题link.cut要求不能换根,当然也保证link时其中一个点必定已经是根. 方法: void link(Node *x, ...

  2. 一堆LCT板子

    搞了一上午LCT,真是累死了-- 以前总觉得LCT高大上不好学不好打,今天打了几遍感觉还可以嘛= =反正现在的水平应付不太难的LCT题也够用了,就这样好了,接下来专心搞网络流. 话说以前一直YY不出来 ...

  3. 动态树之LCT(link-cut tree)讲解

    动态树是一类要求维护森林的连通性的题的总称,这类问题要求维护某个点到根的某些数据,支持树的切分,合并,以及对子树的某些操作.其中解决这一问题的某些简化版(不包括对子树的操作)的基础数据结构就是LCT( ...

  4. 在此为LCT开一个永久的坑

    其实我连splay都还不怎么会. 今天先抄了黄学长的bzoj2049,以后一定要把它理解了. 写LCT怎么能不%数据结构大神yeweining呢?%%%chrysanthemums  %%%切掉大森林 ...

  5. 【BZOJ2157】旅游 LCT

    模板T,SB的DMoon..其实样例也是中国好样例...一开始不会复制,yangyang:找到“sample input”按住shift,按page down.... #include <ios ...

  6. 【BZOJ3669】[Noi2014]魔法森林 LCT

    终于不是裸的LCT了...然而一开始一眼看上去这是kruskal..不对,题目要求1->n的路径上的每个点的两个最大权值和最小,这样便可以用LCT来维护一个最小生成路(瞎编的...),先以a为关 ...

  7. 【BZOJ1180】: [CROATIAN2009]OTOCI & 2843: 极地旅行社 LCT

    竟然卡了我....忘记在push_down先下传父亲的信息了....还有splay里for():卡了我10min,但是双倍经验还是挺爽的,什么都不用改. 感觉做的全是模板题,太水啦,不能这么水了... ...

  8. 【BZOJ3282】Tree LCT

    1A爽,感觉又对指针重怀信心了呢= =,模板题,注意单点修改时splay就好,其实按吾本意是没写的也A了,不过应该加上能更好维护平衡性. ..还是得加上好= = #include <iostre ...

  9. BZOJ2888 资源运输(LCT启发式合并)

    这道题目太神啦! 我们考虑他的每一次合并操作,为了维护两棵树合并后树的重心,我们只好一个一个的把节点加进去.那么这样一来看上去似乎就是一次操作O(nlogn),但是我们拥有数据结构的合并利器--启发式 ...

随机推荐

  1. MS Office CVE-2015-1641 恶意 Exploit 样本分析

    MS Office CVE-2015-1641 恶意 Exploit 样本分析 在对最近的一个恶意 MS Office 文档样本进行分析时,我们发现了一些有趣的特性.这个文档利用 CVE-2015-1 ...

  2. 在jsp中接收并处理servlet传过来的含有bean的List

    在jsp中接收并处理servlet传过来的含有bean的List 例如有以下bean package com.test.domain; class Student{ private Stirng na ...

  3. TcxScheduler的使用2

    DevExpress 行事历(Scheduler)的常用属性.事件和方法 参考资料来源:附带的ExpressScheduler 2  Demo, 如想了解更多可以查看Demo. 一.TcxSchedu ...

  4. 打包egg

    scrapyd-deploy -p chahao -v 1.0 --build-egg chahao.egg

  5. Flask小demo---代码统计系统

    功能要求: 管理员登录 # 第一天 班级管理 # 第一天 学生管理 # 第一天 学生登录 上传代码(zip文件和.py文件) 查看个人提交记录列表 highchar统计 学生列表上方使用柱状图展示现班 ...

  6. Python3 出现'ascii' codec can't encode characters问题

    当使用urllib.request.urlopen打开包含中文的链接时报错: from urllib import request url = 'https://baike.baidu.com/ite ...

  7. DOS命令基础,包涵DOS库说明书

    20种常用的DOS命令小结 作者: 字体:[增加 减小] 类型:转载   DOS命令总共大约有一百个(包括文本编辑.查杀病毒.配置文件.批处理等),我们这里详细介绍二十个常用的DOS命令     先介 ...

  8. git ——本地项目上传到git

    1.(先进入项目文件夹)通过命令 git init 把这个目录变成git可以管理的仓库 git init 2.把文件添加到版本库中,使用命令 git add .添加到暂存区里面去,不要忘记后面的小数点 ...

  9. [java笔记]动态数组

    private int count;//计数器 private int ary[] = new int [3]; if(count >= ary.length){ //数组动态扩展 int ne ...

  10. java IO流之——File类知识总结和面试

    File类描述的是一个文件或文件夹.(文件夹也可以称为目录).该类的出现是对文件系统的中的文件以及文件夹进行对象的封装.可以通过对象的思想来操作文件以及文件夹.可以用面向对象的处理问题,通过该对象的方 ...