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. 梦想MxWeb3D,三维CAD协同设计平台 2019.05.05更新

    SDK开发包下载地址: http://www.mxdraw.com/ndetail_20140.html 在线演示网址: http://www.mxdraw.com:3000/ 1.  增加CAD绘图 ...

  2. java学习_5_24

    TreeMap底层是用红黑树实现的,源码如下: /** * A Red-Black tree based {@link NavigableMap} implementation. * The map ...

  3. webpack3 + vue 添加 serviceWorker

    新的vue脚手架已经可以自带pwa了,本文主要针对旧版的webpack. 先装三个插件: $npm i register-service-worker sw-precache-webpack-plug ...

  4. Jmeter学习笔记之逻辑控制器-Runtime Controller

    文章目录 Runtime Controller介绍 Runtime Controller 编辑界面 Once Only Controller介绍 Once Only Controller 配置界面 O ...

  5. 18年多校-1002 Balanced Sequence

    >>点击进入原题测试<< 思路:自己写没写出来,想不通该怎么排序好,看了杜神代码后补题A掉的.重新理解了一下优先队列中重载小于号的含义,这里记录一下这种排序方式. #inclu ...

  6. HDU 1249 三角形的分割

    可以将三角形的三条边一条一条加进图形中观察 假设添加第n个三角形 前n-1个三角形将区域划分为sum[n-1] 第n个三角形每条边最多能经过前n-1个三角形每条三角形的两条边 , 一条边切完增加了 2 ...

  7. Uva12657 Boxes in a Line

    题目链接:传送门 分析:每次操作都会花费大量时间,显然我们只需要关注每个元素的左边是啥,右边是啥就够了,那么用双向链表,l[i]表示i左边的数,r[i]表示i右边的数,每次操作模拟一下数组的变化就好了 ...

  8. noip模拟赛 排列

    [问题描述] 给出一个随机的排列,请你计算最大值减最小值的差小于等于0~n-1的区间分别有多少个. 输入格式 输入文件名为sum.in. 第一行一个数T(<=10),表示数据组数 对于每一组数据 ...

  9. 苹果树(codevs 1228)

    题目描述 Description 在卡卡的房子外面,有一棵苹果树.每年的春天,树上总会结出很多的苹果.卡卡非常喜欢吃苹果,所以他一直都精心的呵护这棵苹果树.我们知道树是有很多分叉点的,苹果会长在枝条的 ...

  10. [codeVS1404] 字符串匹配

    时间限制: 1 s 空间限制: 128000 KB 题目等级 : 大师 Master         题目描述 Description 给你两个串A,B,可以得到从A的任意位开始的子串和B匹配的长度. ...