lct是一种动态树,用来维护一些动态加边删边的操作的东西.他主要用到几个操作,其实这个算法和树链刨分有点像,但是不能用线段树简单维护,所以我们要用多棵平衡树来维护树上的一个个子树,然后就进行一些很秀的操作.详情见这个博客:FlashHu

这个博客讲的是真的好,特别适合新手看,而且特别细节,(特别带劲).现在我就可以上代码:

模板:

#include <iostream>
#include <cassert>
#include <cstdio>
#include <cmath>
#include <ctime>
#include <queue>
#include <algorithm>
#include <cstring>
using namespace std;
#define duke(i, a, n) for (register int i = a; i <= n; i++)
#define lv(i, a, n) for (register int i = a; i >= n; i--)
#define clean(a) memset(a, 0, sizeof(a))
const int INF = << ;
typedef long long ll;
typedef double db;
template <class T>
void read(T &x) {
char c;
bool op = ;
while (c = getchar(), c < '' || c > '')
if (c == '-')
op = ;
x = c - '';
while (c = getchar(), c >= '' && c <= '') x = x * + c - '';
if (op)
x = -x;
}
template <class T>
void write(T x) {
if (x < )
putchar('-'), x = -x;
if (x >= )
write(x / );
putchar('' + x % );
}
const int N = ;
struct node {
int fa, ch[], rev, v, s;
} a[N];
int st[N];
#define O(a) cout << #a << " " << a << endl;
int n, m;
bool isroot(int x) { return !(a[a[x].fa].ch[] == x || a[a[x].fa].ch[] == x); }
void pushr(int x) {
swap(a[x].ch[], a[x].ch[]);
a[x].rev ^= ;
}
void push_down(int k) {
if (a[k].rev) {
if (a[k].ch[])
pushr(a[k].ch[]);
if (a[k].ch[])
pushr(a[k].ch[]);
a[k].rev ^= ;
}
}
void push_up(int x) { a[x].s = a[a[x].ch[]].s ^ a[a[x].ch[]].s ^ a[x].v; }
void connect(int x, int fa, int son) {
a[x].fa = fa;
a[fa].ch[son] = x;
}
int iden(int x) { return a[a[x].fa].ch[] == x ? : ; }
void rotate(int x) {
int y = a[x].fa;
int mroot = a[y].fa;
int mrootson = iden(y);
int yson = iden(x);
int b = a[x].ch[yson ^ ];
if (!isroot(y)) {
a[mroot].ch[mrootson] = x;
}
a[x].fa = mroot;
connect(b, y, yson);
connect(y, x, yson ^ );
push_up(y);
push_up(x);
}
void splay(int x) {
int top = ;int i;
st[++top] = x;
for (i = x; !isroot(i); i = a[i].fa) {
st[++top] = a[i].fa;
}
for (int i = top; i >= ; i--) {
push_down(st[i]);
}
while (!isroot(x)) {
int y = a[x].fa;
if (isroot(y)) {
rotate(x);
} else if (iden(x) == iden(y)) {
rotate(y);
rotate(x);
} else {
rotate(x);
rotate(x);
}
}
push_up(x);
}
void access(int x) {
int t = ;
while (x) {
splay(x);
a[x].ch[] = t;
push_up(x);
t = x;
x = a[x].fa;
}
}
void make_root(int x) {
access(x);
splay(x);
// a[a[x].ch[0]].rev ^= 1;
// a[a[x].ch[1]].rev ^= 1;
pushr(x);
// swap(a[x].ch[0],a[x].ch[1]);
// push_down(x);
}
void split(int x, int y) {
// if (x <= n && y <= n) {
make_root(x);
access(y);
splay(y);
// }
}
int findroot(int x) {
access(x);
splay(x);
push_down(x);
while (a[x].ch[]){
push_down(a[x].ch[]);
x = a[x].ch[];
}
return x;
}
void link(int x, int y) {
make_root(x);
int t = findroot(y);
assert(t);
if ( t != x)
a[x].fa = y;
}
void cut(int x, int y) {
make_root(x);
int t = findroot(y);
assert(t);
if (t == x && a[x].fa == y && !a[x].ch[]) {
a[x].fa = a[y].ch[] = ;
push_up(y);
}
}
int main() {
// freopen("in.in","r",stdin);
int x, y, typ;
read(n);
read(m);
duke(i, , n) { read(a[i].v); push_up(i); }
int oup = ;
duke(mi,,m){
read(typ);
read(x);
read(y);
if (typ == ) {
split(x, y);
printf("%d\n", a[y].s);
++oup; } else if (typ == ) {
link(x, y);
} else if (typ == ) {
cut(x, y);
} else {
splay(x);
a[x].v = y;
}
// cout<<a[1].ch[0]<<" "<<a[1].ch[1]<<" "<<a[1].fa<<" "<<a[1].v<<" "<<a[1].s<<endl;
}
return ;
}

魔法森林:

// luogu-judger-enable-o2
#include<iostream>
#include<cstdio>
#include<cmath>
#include<ctime>
#include<queue>
#include<algorithm>
#include<cstring>
using namespace std;
#define duke(i,a,n) for(register int i = a;i <= n;i++)
#define lv(i,a,n) for(register int i = a;i >= n;i--)
#define clean(a) memset(a,0,sizeof(a))
const int INF = << ;
typedef long long ll;
typedef double db;
template <class T>
void read(T &x)
{
char c;
bool op = ;
while(c = getchar(), c < '' || c > '')
if(c == '-') op = ;
x = c - '';
while(c = getchar(), c >= '' && c <= '')
x = x * + c - '';
if(op) x = -x;
}
template <class T>
void write(T x)
{
if(x < ) putchar('-'), x = -x;
if(x >= ) write(x / );
putchar('' + x % );
}
#define min2(x,y) if(x>y)x=y;
const int N = 2e5 + ;
const int P = ;
struct node
{
int fa,ch[],rev,v,mx;
}a[N];
int st[N],n,m;
struct edge
{
int u,v,a,b;
bool operator < (const edge &oth) const
{
return a < oth.a;
}
void getin()
{
read(u);read(v);
read(a);read(b);
u |= P;v |= P;
}
}e[ * N];
bool isroot(int x)
{
return a[a[x].fa].ch[] != x && a[a[x].fa].ch[] != x;
}
void pushr(int x)
{
swap(a[x].ch[],a[x].ch[]);
a[x].rev ^= ;
}
void push_down(int x)
{
if(a[x].rev)
{
// if(a[a[x].ch[0]].rev) pushr(a[x].ch[0]);
// if(a[a[x].ch[1]].rev) pushr(a[x].ch[1]);
swap(a[x].ch[],a[x].ch[]);
a[a[x].ch[]].rev ^= ;
a[a[x].ch[]].rev ^= ;
a[x].rev ^= ;
}
}
void push_up(int x)
{
a[x].mx = x;
if(e[a[x].mx].b < e[a[a[x].ch[]].mx].b) a[x].mx = a[a[x].ch[]].mx;
if(e[a[x].mx].b < e[a[a[x].ch[]].mx].b) a[x].mx = a[a[x].ch[]].mx;
}
int iden(int x)
{
return a[a[x].fa].ch[] == x ? : ;
}
void connect(int x,int fa,int son)
{
a[x].fa = fa;
a[fa].ch[son] = x;
}
void rotate(int x)
{
int y = a[x].fa;
int mroot = a[y].fa;
int mrootson = iden(y);
int yson = iden(x);
int b = a[x].ch[yson ^ ];
if(!isroot(y))
{
a[mroot].ch[mrootson] = x;
}
a[x].fa = mroot;
connect(y,x,yson ^ );
connect(b,y,yson);
push_up(y);
// update(x);
}
void splay(int x)
{
int top = ,i;
st[++top] = x;
for(i = x;!isroot(i);i = a[i].fa)
{
st[++top] = a[i].fa;
}
push_down(a[i].fa);
for(int i = top;i;i--)
{
push_down(st[i]);
}
while(!isroot(x))
{
int y = a[x].fa;
if(isroot(y)) rotate(x);
else if(iden(x) == iden(y))
{
rotate(y);rotate(x);
}
else
{
rotate(x);rotate(x);
}
}
push_up(x);
}
void access(int x)
{
int t = ;
while(x)
{
splay(x);
a[x].ch[] = t;
push_up(x);
t = x;
x = a[x].fa;
}
}
void makeroot(int x)
{
access(x);
splay(x);
a[x].rev ^= ;
}
int findroot(int x)
{
access(x);
splay(x);
while(a[x].ch[])
x = a[x].ch[];
return x;
}
void link(int x)
{
int y = e[x].u,z = e[x].v;
makeroot(z);
a[a[z].fa = x].fa = y;
// a[x].fa = y;
}
void cut(int x)
{
access(e[x].v);
splay(x);
a[x].ch[] = a[x].ch[] = a[a[x].ch[]].fa = a[a[x].ch[]].fa = ;
push_up(x);
}
int main()
{
// freopen("2387.in","r",stdin);
int ans = INF;
read(n);read(m);
duke(i,,m)
{
e[i].getin();
}
sort(e + ,e + m + );
int y,z;
duke(i,,m)
{
if((y = e[i].u) == (z = e[i].v)) continue;
makeroot(y);
if(y != findroot(z)) link(i);
else if(e[i].b < e[a[z].mx].b)
{
cut(a[z].mx);
link(i);
}
makeroot( | P);
if(( | P) == findroot(n | P))
ans = min(ans,e[i].a + e[a[n | P].mx].b);
}
printf("%d\n",ans == INF ? - : ans);
return ;
}

弹飞绵羊:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<queue>
#include<algorithm>
#include<vector>
#include<complex>
#include<cstring>
using namespace std;
#define duke(i,a,n) for(int i = a;i <= n;i++)
#define lv(i,a,n) for(int i = a;i >= n;i--)
#define clean(a) memset(a,0,sizeof(a))
#define mp make_pair
#define cp complex<db>
#define enter puts("")
const long long INF = 1LL << ;
const double eps = 1e-;
typedef long long ll;
typedef double db;
template <class T>
void read(T &x)
{
char c;
bool op = ;
while(c = getchar(), c < '' || c > '')
if(c == '-') op = ;
x = c - '';
while(c = getchar(), c >= '' && c <= '')
x = x * + c - '';
if(op) x = -x;
}
template <class T>
void write(T x)
{
if(x < ) putchar('-'), x = -x;
if(x >= ) write(x / );
putchar('' + x % );
}
struct node
{
int ch[],siz,fa;
}a[];
int n,m;
int iden(int x)
{
return a[a[x].fa].ch[] == x ? : ;
}
void connect(int x,int fa,int son)
{
a[x].fa = fa;
a[fa].ch[son] = x;
}
bool isroot(int x)
{
return a[a[x].fa].ch[] != x && a[a[x].fa].ch[] != x;
}
void push_up(int x)
{
a[x].siz = a[a[x].ch[]].siz + a[a[x].ch[]].siz + ;
}
/*void pushr(int x)
{
swap(a[x].ch[0],a[x].ch[1]);
a[x].rev ^= 1;
}
void push_down(int x)
{
if(a[x].rev)
{
if(a[x].ch[0]) pushr(a[x].ch[0]);
if(a[x].ch[1]) pushr(a[x].ch[1]);
a[x].rev ^= 1;
}
}*/
void rotate(int x)
{
int y = a[x].fa;
int mroot = a[y].fa;
int mrootson = iden(y);
int yson =iden(x);
int b = a[x].ch[yson ^ ];
if(!isroot(y))
{
a[mroot].ch[mrootson] = x;
}
a[x].fa = mroot;
connect(b,y,yson);
connect(y,x,yson ^ );
push_up(y);
}
/*inline bool isroot(int x){
return a[a[x].fa].ch[0]==x||a[a[x].fa].ch[1]==x;
}
void rotate(int x){
int y=a[x].fa,z=a[y].fa,k=a[y].ch[1]==x,w=a[x].ch[!k];
if(isroot(y))a[z].ch[a[z].ch[1]==y] = x;a[x].ch[!k]=y;a[y].ch[k]=w;
if(w)a[w].fa=y;a[y].fa=x;a[x].fa=z;
push_up(y);
}*/
void splay(int x)
{
while(!isroot(x))
{
int y = a[x].fa;
if(isroot(y)) rotate(x);
else if(iden(x) == iden(y))
{
rotate(y);rotate(x);
}
else
{
rotate(x);rotate(x);
}
}
push_up(x);
}
/*void splay(int x){
int y,z;
while(isroot(x)){
y=a[x].fa;z=a[y].fa;
cout<<x<<endl;
if(isroot(y))
rotate((a[y].ch[0]==x)^(a[z].ch[0]==y)?y:x);
rotate(x);
}
push_up(x);
}*/
void access(int x)
{
int t = ;
while(x)
{
splay(x);
a[x].ch[] = t;
t = x;
push_up(x);
x = a[x].fa;
}
}
int ch,j,k;
int main()
{
// freopen("3203.in","r",stdin);
read(n);
duke(i,,n)
{
a[i].siz = ;
read(k);
if(i + k <= n)
a[i].fa = i + k;
}
read(m);
while(m--)
{
read(ch);
if(ch == )
{
read(j);j++;
access(j);splay(j);
printf("%d\n",a[j].siz);
}
else
{
read(j);read(k); ++j;
access(j);splay(j);
a[j].ch[] = a[a[j].ch[]].fa = ;
if(j + k <= n) a[j].fa = j + k;
push_up(j);
}
}
return ;
}
/*int main()
{
freopen("3203.in","r",stdin);
register char ch;
int n,m,j,k;
read(n);
for(j=1;j<=n;++j){
a[j].siz=1;
read(k);
if(j+k<=n)a[j].fa=j+k;//如果弹飞了就不连边
}
read(m);
int op = 0;
while(m--){
read(op);
if(op&1){
read(j);++j;
access(j);splay(j);//直接查询
printf("%d\n",a[j].siz);
}
else{
read(j);read(k);++j;
access(j);splay(j);
a[j].ch[0]=a[a[j].ch[0]].fa=0;//直接断边
if(j+k<=n)a[j].fa=j+k;//直接连边
push_
up(j);
}
}
return 0;
}*/

洞穴勘测:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<ctime>
#include<queue>
#include<algorithm>
#include<cstring>
using namespace std;
#define duke(i,a,n) for(register int i = a;i <= n;i++)
#define lv(i,a,n) for(register int i = a;i >= n;i--)
#define clean(a) memset(a,0,sizeof(a))
const int INF = << ;
typedef long long ll;
typedef double db;
template <class T>
void read(T &x)
{
char c;
bool op = ;
while(c = getchar(), c < '' || c > '')
if(c == '-') op = ;
x = c - '';
while(c = getchar(), c >= '' && c <= '')
x = x * + c - '';
if(op) x = -x;
}
template <class T>
void write(T x)
{
if(x < ) putchar('-'), x = -x;
if(x >= ) write(x / );
putchar('' + x % );
}
struct node
{
int fa,ch[],rev;
}a[];
int n,m,st[];
bool isroot(int x)
{
return a[a[x].fa].ch[] != x && a[a[x].fa].ch[] != x;
}
void push_down(int k)
{
if(a[k].rev)
{
int l = a[k].ch[];
int r = a[k].ch[];
a[k].rev ^= ;
a[l].rev ^= ;
a[r].rev ^= ;
swap(a[k].ch[],a[k].ch[]);
}
}
int iden(int x)
{
return a[a[x].fa].ch[] == x ? : ;
}
void connect(int x,int f,int son)
{
a[x].fa = f;
a[f].ch[son] = x;
}
void rotate(int x)
{
int y = a[x].fa;
int mroot = a[y].fa;
int mrootson = iden(y);
int yson = iden(x);
int b = a[x].ch[yson ^ ];
if(!isroot(y))
{
a[mroot].ch[mrootson] = x;
}
a[x].fa = mroot;
connect(b,y,yson);
connect(y,x,yson ^ );
}
void splay(int x)
{
int top = ;
st[++top] = x;
for(int i = x;!isroot(i);i = a[i].fa)
{
st[++top] = a[i].fa;
// cout<<"gg"<<endl;
}
// cout<<"out"<<endl;
for(int i = top;i;i--)
push_down(st[i]);
while(!isroot(x))
{
int y = a[x].fa;
if(isroot(y)) rotate(x);
else if(iden(x) == iden(y))
{
rotate(y);rotate(x);
}
else
{
rotate(x);rotate(x);
}
// cout<<"233"<<endl;
}
}
void access(int x)
{
int t = ;
while(x)
{
splay(x);
a[x].ch[] = t;
t = x;
x = a[x].fa;
}
}
void rever(int x)
{
access(x);
splay(x);
a[x].rev ^= ;
}
void link(int x,int y)
{
rever(x);a[x].fa = y;
splay(x);
// cout<<x<<" "<<y<<endl;
}
void cut(int x,int y)
{
rever(x);
access(y);
splay(y);
a[y].ch[] = a[x].fa = ;
}
int find(int x)
{
// cout<<x<<endl;
access(x);//cout<<"yes"<<endl;
splay(x);
int y = x;
//cout<<"!!!"<<y<<endl;
while(a[y].ch[])
y = a[y].ch[];
// cout<<y<<endl;
return y;
}
int main()
{
// freopen("2147.in","r",stdin);
char ch[];
int x,y;
read(n);read(m);
duke(i,,m)
{
scanf("%s",ch);
read(x);read(y);
if(ch[] == 'C') link(x,y);
else if(ch[] == 'D') cut(x,y);
else
{
if(find(x) == find(y)) printf("Yes\n");
else
printf("No\n");
}
}
return ;
}

LCT教程的更多相关文章

  1. Link-Cut Tree(LCT) 教程

    目录 前置知识 介绍 Access FindRoot MakeRoot Split Link Cut 关于Splay中操作的一点说明: 模板 前置知识 请先对树链剖分和Splay有所了解.LCT基于树 ...

  2. LCT 模板及套路总结

    这一个月貌似已经考了无数次\(LCT\)了..... 保险起见还是来一发总结吧..... A. LCT 模板 \(LCT\) 是由大名鼎鼎的 \(Tarjan\) 老爷发明的. 主要是用来维护树上路径 ...

  3. [洛谷日报第62期]Splay简易教程 (转载)

    本文发布于洛谷日报,特约作者:tiger0132 原地址 分割线下为copy的内容 [洛谷日报第62期]Splay简易教程 洛谷科技 18-10-0223:31 简介 二叉排序树(Binary Sor ...

  4. OI知识点|NOIP考点|省选考点|教程与学习笔记合集

    点亮技能树行动-- 本篇blog按照分类将网上写的OI知识点归纳了一下,然后会附上蒟蒻我的学习笔记或者是我认为写的不错的专题博客qwqwqwq(好吧,其实已经咕咕咕了...) 基础算法 贪心 枚举 分 ...

  5. Angular2入门系列教程7-HTTP(一)-使用Angular2自带的http进行网络请求

    上一篇:Angular2入门系列教程6-路由(二)-使用多层级路由并在在路由中传递复杂参数 感觉这篇不是很好写,因为涉及到网络请求,如果采用真实的网络请求,这个例子大家拿到手估计还要自己写一个web ...

  6. Angular2入门系列教程6-路由(二)-使用多层级路由并在在路由中传递复杂参数

    上一篇:Angular2入门系列教程5-路由(一)-使用简单的路由并在在路由中传递参数 之前介绍了简单的路由以及传参,这篇文章我们将要学习复杂一些的路由以及传递其他附加参数.一个好的路由系统可以使我们 ...

  7. Angular2入门系列教程5-路由(一)-使用简单的路由并在在路由中传递参数

    上一篇:Angular2入门系列教程-服务 上一篇文章我们将Angular2的数据服务分离出来,学习了Angular2的依赖注入,这篇文章我们将要学习Angualr2的路由 为了编写样式方便,我们这篇 ...

  8. Angular2入门系列教程4-服务

    上一篇文章 Angular2入门系列教程-多个组件,主从关系 在编程中,我们通常会将数据提供单独分离出来,以免在编写程序的过程中反复复制粘贴数据请求的代码 Angular2中提供了依赖注入的概念,使得 ...

  9. Angular2入门系列教程1-使用Angular-cli搭建Angular2开发环境

    一直在学Angular2,百忙之中抽点时间来写个简单的教程. 2016年是前端飞速发展的一年,前端越来越形成了(web component)组件化的编程模式:以前Jquery通吃一切的田园时代一去不复 ...

随机推荐

  1. JS中的let和var的区别

    最近很多前端的朋友去面试被问到let和var的区别,其实阮一峰老师的ES6中已经很详细介绍了let的用法和var的区别.我简单总结一下,以便各位以后面试中使用. ES6 新增了let命令,用来声明局部 ...

  2. clock_gettime 用法

    #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/sta ...

  3. 洛谷——P2158 [SDOI2008]仪仗队

    P2158 [SDOI2008]仪仗队 找规律大水题嘛,如果你做过P1170 兔八哥与猎人 这题得到的规律是$a,b,c,d$,若$gcd(a-b,c-d)==1$ 那么$a,b$就能看到$c,d$ ...

  4. 搭建私有docker仓库

    安装docker yum install docker 启动docker systemctl start docker 拉取registry镜像 docker pull registry 创建仓库配置 ...

  5. css3--伪元素和伪类

    1,定义 W3C定义:伪元素伪类 都可以向某些选择器设置特殊效果.(css2中定义) css3中的定义: 1).伪元素:在DOM树中创建了一些抽象元素(虚拟的容器).由两个冒号::开头(css2中并没 ...

  6. WeChat-小程序-tabbar

    WeChat-小程序-tabbar https://developers.weixin.qq.com/miniprogram/dev/framework/config.html#%E5%85%A8%E ...

  7. 封装的一些常见的JS DOM操作和数据处理的函数.

    //用 class 获取元素 function getElementsByClass(className,context) { context = context || document; if(do ...

  8. 【Codeforces 476C】Dreamoon and Sums

    [链接] 我是链接,点我呀:) [题意] 让你求出所有x的和 其中 (x div b)是(x mod b)的倍数 且x mod b不等于0 且(x div b)除(x mod b)的值(假设为k),k ...

  9. POJ 3101 大数+gcd

    题目大意: 星星作圆周运动的周期给出,若已连成一条线,下一次所有星星在同一条线上的时间 用分数形式输出 这里我们可以利用追及问题来计算出两个星星之间连成一条直线的时间,也即速度快的星星追上速度慢的星星 ...

  10. 4种OSS的应用架构及核心技术

        基础型 架构描述:OSS作为文件存储源,用户上传下载数据均经过ECS与OSS通信. 解决用户问题:文件空间大,ECS磁盘存储空间有限:多ECS间无法同步数据. 适用场景描述:文件较多,但文件调 ...