您的位置:首页 > 理论基础 > 数据结构算法

动态树LCT总结

2014-08-20 17:06 597 查看
动态树中最关键的一个函数就是Access,利用Access可以把x到树根的路径暴露出来,并把无关的部分剪掉,形成一颗Splay树。利用Splay树,我们能够任意改变树的形态,它们之间的树形结构并不发生改变。严格上来说,树形结构应该是发生了改变,但它们间的相互位置并不变化,这就是Splay的优点。

在求解LCA的问题上,第一次Access(u)保证了u到树根形成了一颗Splay,并清晰地暴露出来。第二次Access(v)则会把v到树根形成一个Splay,并把LCA与u之间的部分剪掉。因为遇到LCA后,就一定有Splay(LCA),所以最后的终止条件一直是LCA。

代码如下:

/*
SPOJ 375
Author: gmcather
*/
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
using namespace std;

#define maxn 11000

int head[maxn*2],to[maxn*2],nxt[maxn*2];
int cnt,idx[maxn*2],wei[maxn*2],id[maxn];
int val[maxn],Max[maxn],pre[maxn],ch[maxn][2];
bool rt[maxn];

void add(int u,int v,int i,int w){
to[cnt]=v;nxt[cnt]=head[u];wei[cnt]=w;
idx[cnt]=i;head[u]=cnt++;
}

void dfs(int u){
for(int j=head[u];j!=-1;j=nxt[j]){
int v=to[j];
if(pre[v]) continue;
pre[v]=u;id[idx[j]]=v;val[v]=wei[j];
dfs(v);
}
}

void push_up(int x){
Max[x]=max(max(Max[ch[x][0]],Max[ch[x][1]]),val[x]);
}

void Rotate(int x,int f){
int y=pre[x];
ch[y][f]=ch[x][!f];
pre[ch[x][!f]]=y;
pre[x]=pre[y];
if(!rt[y]) ch[pre[y]][ch[pre[y]][1]==y]=x;
else rt[x]=true,rt[y]=false;
pre[y]=x;
ch[x][!f]=y;
push_up(y);
}

void Splay(int x){
while(!rt[x]){
if(rt[pre[x]]) Rotate(x,ch[pre[x]][1]==x);
else{
int y=pre[x];int f=ch[y][1]==x;
if(ch[pre[y]][f]==y){
Rotate(y,f);Rotate(x,f);
}
else{
Rotate(x,f);Rotate(x,!f);
}
}
}
push_up(x);
}

void Access(int x){
for(int y=0;x;x=pre[y=x]){
Splay(x);
rt[ch[x][1]]=true;rt[ch[x][1]=y]=false;
push_up(x);
}
}

int lca(int &u,int &v){
Access(v);v=0;
for(;u;u=pre[v=u]){
Splay(u);
if(!pre[u]) break;
rt[ch[u][1]]=true;rt[ch[u][1]=v]=false;
push_up(u);
}
return max(Max[ch[u][1]],Max[v]);
}

int main(){
freopen("1.txt","r",stdin);
int t;scanf("%d",&t);
while(t--){
int n;
scanf("%d",&n);
memset(head,-1,sizeof(head));cnt=0;
for(int i=1;i<n;i++){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
add(a,b,i,c);
add(b,a,i,c);
}
for(int i=0;i<=n;i++){
pre[i]=ch[i][0]=ch[i][1]=0;
rt[i]=true;
}
pre[1]=-1;
dfs(1);
pre[1]=0;
for(int i=0;i<=n;i++) Max[i]=val[i];
Max[0]=-2000000000;
while(true){
char s[20];int a,b;
scanf("%s",s);
if(s[0]=='D') break;
else if(s[0]=='Q'){
scanf("%d%d",&a,&b);
printf("%d\n",lca(a,b));
}
else if(s[0]=='C'){
scanf("%d%d",&a,&b);
val[id[a]]=b;
push_up(id[a]);
}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  数据结构