考虑\(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. sru源码--language model

    import sys import os import argparse import time import random import math import numpy as np import ...

  2. 聊天室(下篇)GatewayWorker 与 Laravel 的整合

    思路 上一篇大概梳理了一下 GatewayWorker 的基础知识.这篇就来准备整合 GatewayWorker 到 Laravel. GatewayWorker 是基于 Socket 监听的服务器框 ...

  3. ajax局部刷新后里面的jquery事件失效的解决方法

    live() 与bind()作用基本一样. 最重要区别:live()可以将事件绑定到当前和将来的元素(eg:为id=zy元素绑定点击事件,而当你用js动态生成一个节点并插入到dom文档结构中时,如果你 ...

  4. TableView 的那些坑

    1. 分割线填满cell宽度, 并且设置分割线的颜色 1.1 利用系统的分割线填充 1.1.1 tableView 设置如下属性 // 给tableView设置如下属性值 tableView.layo ...

  5. mysql -> 事务&事务锁_09

    事务的特性 redo undo 锁的隔离级别

  6. python基础--shutil模块

    shutil模块提供了大量的文件的高级操作. 特别针对文件拷贝和删除,主要功能为目录和文件操作以及压缩操作.对单个文件的操作也可参见os模块. 注意 即便是更高级别的文件复制函数(shutil.cop ...

  7. invalid byte sequence for encoding "UTF8": 0xe99d2c

    服务器还原数据库数据出错,老规矩... 字符集编码的问题 http://blog.csdn.net/beiigang/article/details/39582583 over....

  8. 客户端使用less方法

    <link rel="stylesheet/less" type="text/css" href="/css/style.less"& ...

  9. JDBC核心API

    JDBC核心API在java.sql.*和javax.sql.* 1.Driver接口:表示Java驱动程序接口,具体的数据库厂商要实现其此接口 connect(url.propertis):连接数据 ...

  10. 20165333 实验二 Java面向对象程序设计

    姓名:陈国超 学号:20165333 班级:1653 实验课程:JAVA程序设计 实验名称:Java面向对象程序设计 实验时间:2018.4.14 指导老师:娄家鹏 实验内容及步骤 (一) " ...