说好的专题。。。
lct的一些概念看论文 杨哲《QTREE解法的一些研究》 简单易懂。
首先不要把lct想象得很难,其实很水的。lct就是很多splay树维护的树。。。
lct的access操作就是在原树中拓展一条点到根的类二叉树出来(用splay来维护)
这里,splay树是按深度作为关键字的,当然,在无向图中(无环)可以任意指定一个点为根,这点要切记(因为在这里操作时,有些操作需要换根,所以一定要理解)
link操作就是将点作为这颗类二叉树的根,然后合并
cut操作就是将点作为这颗二叉树的根,然后在拓展一条另一个点的splay路径(此时这两个点一定要有边连接,这样使得拓展上来的根一定在另一个点拓展上来的splay树的左子树上,因为他们有边连接),将左子树的父亲设为0,并且去掉左子树
getroot操作就是将点拓展了splay后,并且将它伸展到根,此时,最小的子树(深度最浅,即最左的子树)就是这颗splay的根
makeroot操作就是将点拓展为现在所在的树的根,即换根,伸展到根后只需要将左右子树反向,就是将深度换了(根据splay有良好的下放操作,我们将翻转用标记来翻转,使得时间复杂度减小)
额,我自己都觉得说得不好 。。囧
说些注意的地方吧:
好了,我认为差不多了。。
一些题我之前也发了博文,我现在再放出来。。
【BZOJ】2002: [Hnoi2010]Bounce 弹飞绵羊
#include <cstdio>
#define read(x) x=getint()
using namespace std;
inline int getint() { char c; int ret=0; for(c=getchar(); c<‘0‘ || c>‘9‘; c=getchar()); for(; c>=‘0‘ && c<=‘9‘; c=getchar()) ret=ret*10+c-‘0‘; return ret; }
const int N=200005;
struct node* null;
struct node {
node *f, *ch[2];
int s;
void pushup() { s=1+ch[0]->s+ch[1]->s; }
bool d() { return f->ch[1]==this; }
void setc(node* c, bool d) { ch[d]=c; c->f=this; }
bool check() { return f==null || (f->ch[0]!=this && f->ch[1]!=this); } //check操作是lct特地的,因为为了省空间,我们不开n颗splay,只用节点关联就行了,这样就无法避免父亲没有这个孩子的情况。所以还要特判
}*nd[N];
void rot(node* r) {
node* f=r->f; bool d=r->d();
if(f->check()) r->f=f->f;
else f->f->setc(r, f->d()); //这里一定要这样写,不然会让null的孩子改变,这样在splay的循环就会死循环T_T
f->setc(r->ch[!d], d);
r->setc(f, !d);
f->pushup();
}
inline void splay(node* r) {
while(!r->check())
if(r->f->check()) rot(r);
else r->d()==r->f->d()?(rot(r->f), rot(r)):(rot(r), rot(r));
r->pushup();
}
inline void access(node* f) {
for(node* c=null; f!=null; f=f->f) {
splay(f);
f->setc(c, 1);
f->pushup();
c=f;
}
}
inline void link(node* c, node* f) {
access(c); splay(c);
c->ch[0]->f=null; c->ch[0]=null; c->f=f; c->pushup();
}
inline void init() {
null=new node; null->s=0; null->f=null->ch[0]=null->ch[1]=null;
}
int main() {
init();
int n, t; read(n);
for(int i=0; i<n; ++i) { nd[i]=new node; nd[i]->s=1; nd[i]->ch[0]=nd[i]->ch[1]=nd[i]->f=null; }
for(int i=0; i<n; ++i) {
read(t);
if(i+t<n) nd[i]->f=nd[i+t];
}
int m, a, b, c; read(m);
for(int i=0; i<m; ++i) {
read(a); read(b);
if(a==1) {
access(nd[b]);
splay(nd[b]);
printf("%d\n", nd[b]->s);
}
else {
read(c);
if(b+c<n) link(nd[b], nd[b+c]);
else link(nd[b], null);
}
}
return 0;
}
【BZOJ】1036: [ZJOI2008]树的统计Count
#include <cstdio>
#include <iostream>
using namespace std;
#define dbg(x) cout << #x << "=" << x << endl
#define read(x) x=getint()
#define print(x) printf("%d", x)
#define max(a,b) ((a)>(b)?(a):(b))
const int oo=~0u>>1;
inline int getint() { char c; int ret=0, k=1; for(c=getchar(); c<‘0‘ || c>‘9‘; c=getchar()) if(c==‘-‘) k=-1; for(; c>=‘0‘&&c<=‘9‘; c=getchar()) ret=ret*10+c-‘0‘; return k*ret; }
const int N=30010, M=100005;
int ihead[N], inext[M], to[M], cnt, q[N], front, tail, n, m;
bool vis[N];
struct node* null;
struct node {
node* fa, *ch[2];
int w, sum, mx;
bool d() { return fa->ch[1]==this; }
bool check() { return fa->ch[0]!=this && fa->ch[1]!=this; }
void setc(node* c, bool d) { ch[d]=c; c->fa=this; }
void pushup() {
sum=w+ch[0]->sum+ch[1]->sum;
mx=max(w, max(ch[0]->mx, ch[1]->mx));
}
}*nd[N];
inline void rot(node* r) {
node* fa=r->fa; bool d=r->d();
if(fa->check()) r->fa=fa->fa;
else fa->fa->setc(r, fa->d());
fa->setc(r->ch[!d], d);
r->setc(fa, !d);
fa->pushup();
}
inline void splay(node* r) {
while(!r->check())
if(r->fa->check()) rot(r);
else r->d()==r->fa->d()?(rot(r->fa), rot(r)):(rot(r), rot(r));
r->pushup();
}
inline node* access(node* fa) {
node* c=null;
for(; fa!=null; c=fa, fa=fa->fa) {
splay(fa);
fa->setc(c, 1);
fa->pushup();
}
return c;
}
inline void bfs() {
vis[1]=1; int u, v, i;
front=tail=0; q[tail++]=1;
while(front!=tail) {
u=q[front++];
for(i=ihead[u]; i; i=inext[i]) if(!vis[v=to[i]]) {
vis[v]=1;
nd[v]->fa=nd[u];
q[tail++]=v;
}
}
}
inline void add(const int &u, const int &v) {
inext[++cnt]=ihead[u]; ihead[u]=cnt; to[cnt]=v;
inext[++cnt]=ihead[v]; ihead[v]=cnt; to[cnt]=u;
}
int main() {
null=new node; null->fa=null->ch[0]=null->ch[1]=null; null->w=null->sum=0; null->mx=oo+1;
read(n);
int u, v, t;
for(int i=1; i<n; ++i) {
read(u); read(v);
add(u, v);
}
int w;
for(int i=1; i<=n; ++i) {
nd[i]=new node;
read(w);
nd[i]->w=w;
nd[i]->ch[0]=nd[i]->ch[1]=nd[i]->fa=null;
}
bfs();
char c[10];
node* lca=null;
read(m);
int ans;
for(int i=0; i<m; ++i) {
scanf("%s", c);
if(c[0]==‘C‘) {
read(u); read(t);
splay(nd[u]);
nd[u]->w=t;
nd[u]->pushup();
}
else if(c[0]==‘Q‘) {
read(u); read(v);
access(nd[u]);
lca=access(nd[v]);
splay(nd[u]);
if(nd[u]==lca) {
if(c[1]==‘M‘) ans=max(lca->w, lca->ch[1]->mx);
else ans=lca->w + lca->ch[1]->sum;
}
else {
if(c[1]==‘M‘) ans=max(max(lca->w, nd[u]->mx), lca->ch[1]->mx);
else ans=lca->w + lca->ch[1]->sum + nd[u]->sum;
}
printf("%d\n", ans);
}
}
return 0;
}
【BZOJ】2049: [Sdoi2008]Cave 洞穴勘测
#include <cstdio>
#include <cstring>
#include <string>
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
#define rep(i, n) for(int i=0; i<(n); ++i)
#define for1(i,a,n) for(int i=(a);i<=(n);++i)
#define for2(i,a,n) for(int i=(a);i<(n);++i)
#define for3(i,a,n) for(int i=(a);i>=(n);--i)
#define for4(i,a,n) for(int i=(a);i>(n);--i)
#define CC(i,a) memset(i,a,sizeof(i))
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define read(a) a=getnum()
#define print(a) printf("%d", a)
#define dbg(x) cout << #x << "=" << x << endl;
#define dbgarr(a, n) for1(i, 0, n) cout << a[i] << " "; cout << endl
inline int getnum() { int ret=0, k=1; char c; for(c=getchar(); c<‘0‘ || c>‘9‘; c=getchar()) if(c==‘-‘) k=-1; for(; c>=‘0‘ && c<=‘9‘; c=getchar()) ret=ret*10+c-‘0‘; return ret*k; }
const int N=10005;
int n, m;
struct node* null;
struct node {
node* ch[2], *fa;
bool rev;
bool d() const { return fa->ch[1]==this; }
void setc(node* c, bool d) { ch[d]=c; c->fa=this; }
bool check() const { return fa->ch[0]!=this && fa->ch[1]!=this; }
void pushdown() {
if(rev) {
ch[0]->rev^=true;
ch[1]->rev^=true;
swap(ch[0], ch[1]);
rev=false;
}
}
}*nd[N];
inline void rot(node* r) {
node* fa=r->fa; bool d=r->d();
fa->pushdown(); r->pushdown();
if(fa->check()) r->fa=fa->fa;
else fa->fa->setc(r, fa->d());
fa->setc(r->ch[!d], d);
r->setc(fa, !d);
}
void fix(node* x) {
if(!x->check()) fix(x->fa);
x->pushdown();
}
inline void splay(node* r) {
fix(r);
while(!r->check())
if(r->fa->check()) rot(r);
else r->d()==r->fa->d()?(rot(r->fa), rot(r)):(rot(r), rot(r));
}
inline node* access(node* x) {
node* y=null;
for(; x!=null; y=x, x=x->fa) {
splay(x);
x->ch[1]=y;
}
return y;
}
inline void mkroot(node* x) {
access(x)->rev^=true; splay(x);
}
inline void link(node* x, node* y) {
mkroot(x); x->fa=y;
}
inline void cut(node* x, node* y) {
mkroot(x);
access(y); splay(y);
y->ch[0]->fa=null; y->ch[0]=null;
}
inline node* findrt(node* x) {
access(x); splay(x);
while(x->ch[0]!=null) x=x->ch[0];
return x;
}
int main() {
read(n); read(m);
null=new node; null->fa=null->ch[0]=null->ch[1]=null; null->rev=false;
char s[10];
int u, v;
for1(i, 1, n) {
nd[i]=new node;
nd[i]->fa=nd[i]->ch[0]=nd[i]->ch[1]=null; nd[i]->rev=false;
}
rep(i, m) {
scanf("%s", s);
read(u); read(v);
if(s[0]==‘Q‘)
findrt(nd[u])==findrt(nd[v])?(printf("Yes\n")):(printf("No\n"));
else if(s[0]==‘C‘) link(nd[u], nd[v]);
else cut(nd[u], nd[v]);
}
return 0;
}
欢迎大家指正~!!!
动态树之link-cut tree,布布扣,bubuko.com
原文:http://www.cnblogs.com/iwtwiioi/p/3919083.html