【lct】poj2763 Housewife Wind

题意:给你一棵树,边带权,支持两种操作:修改某条边的权值;查询两点之间的最短路。

lct主要实现单点修改和路径和。

修改x结点的值只需将x Splay到其所在辅助树的根,然后修改其值,再maintain一下即可。

路径和询问要这样做:

我们先 ACCESS(u), 然后在 ACCESS(v) 的过程中, 一旦 走到了包含根结点(也就是包含 u)的 Auxiliary Tree, 这时我们走到的结点恰好就是 u 和 v 的最近公共祖 先, 不妨称这个结点为 d. 这时 d 所在的 Auxiliary Tree 中 d 的右子树的 maxcost 即为 u 到 d 的路径的 最大边权, v 所在的 Auxiliary Tree 的 maxcost 则是 v 到 d 的路径的最大边权. 于是我们所求的答案就是 6 这两个 maxcost 中的最大值. 因为 Access 操作的均摊复杂度为 O(log n), 所以回答这个询问所花时间也 是 O(log n) 的.

Update:换了一种写法,能避免边权的鬼畜问题。即在每条边上添加一个虚点,权值为该边边权;而原先的所有点的点权置为零。这样虽然空间多了一倍,但是非常好处理了!(也即,询问可以用先ChangeRoot,再Access,再Splay,再询问左子树的方法了。)

代码更新在最下方。

<法一>

#include<cstdio>
#include<iostream>
#include<stack>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxn 100005
int fa[maxn],c[maxn][2],siz[maxn];
bool is_root[maxn];
int val[maxn],totalval[maxn];
void Maintain(int x)
{
    siz[x]=siz[c[x][0]]+siz[c[x][1]]+1;
    totalval[x]=totalval[c[x][0]]+totalval[c[x][1]]+val[x];
}
void Rotate(int x,bool flag)
{
    int y=fa[x];
    c[y][!flag]=c[x][flag];
    if(c[x][flag]){
        fa[c[x][flag]]=y;
    }
    if(fa[y] && c[fa[y]][c[fa[y]][1]==y]==y){
        c[fa[y]][c[fa[y]][1]==y]=x;
    }
    fa[x]=fa[y];
    c[x][flag]=y;
    fa[y]=x;
    if(is_root[y]){
        is_root[y]=0;
        is_root[x]=1;
    }
    Maintain(y);
    Maintain(x);
}
stack<int>st;
void Splay(int x)
{
    if(!x || is_root[x]){
        return;
    }
    int y;
    while(y=fa[x],(!is_root[x])){
        if(is_root[y]){
            Rotate(x,c[y][0]==x);
        }
        else{
            if((c[y][0]==x)==(c[fa[y]][0]==y)){
                Rotate(y,c[fa[y]][0]==y);
            }
            else{
                Rotate(x,c[y][0]==x);
                y=fa[x];
            }
            Rotate(x,c[y][0]==x);
        }
    }
    Maintain(x);
}
void Spla2(int x)
{
    if(!x || is_root[fa[x]]){
        return;
    }
    int y;
    while(!is_root[y=fa[x]]){
        if(is_root[fa[y]]){
            Rotate(x,c[y][0]==x);
        }
        else{
            if((c[y][0]==x)==(c[fa[y]][0]==y)){
                Rotate(y,c[fa[y]][0]==y);
            }
            else{
                Rotate(x,c[y][0]==x);
                y=fa[x];
            }
            Rotate(x,c[y][0]==x);
        }
    }
    Maintain(x);
}
void Access(int x){
    int y;
    Splay(x);
    while(fa[x]){
        y=fa[x];
        Splay(y);
        if(c[y][1]){
            is_root[c[y][1]]=1;
        }
        is_root[x]=0;
        c[y][1]=x;
        Splay(x);
    }
    if(c[x][1]){
        is_root[c[x][1]]=1;
        c[x][1]=0;
    }
}
int Calc(int x,int y){
    if(x==y){
        return 0;
    }
    Splay(y);
    if(!fa[y]){
        Spla2(x);
        return totalval[c[x][0]]+val[x];
    }
    int z;
    while(fa[y]){
        z=fa[y];
        Splay(z);
        if(!fa[z]){
            return totalval[c[z][1]]+totalval[y];
        }
        if(c[z][1]){
            is_root[c[z][1]]=1;
        }
        is_root[y]=0;
        c[z][1]=y;
        Splay(y);
    }
}
int n,m,cur;
int v[maxn<<1],nex[maxn<<1],first[maxn],w[maxn<<1],e;
void AddEdge(int U,int V,int W){
    v[++e]=V;
    w[e]=W;
    nex[e]=first[U];
    first[U]=e;
}
int bel[maxn];
bool vis[maxn];
void dfs(int U){
    vis[U]=1;
    for(int i=first[U];i;i=nex[i]){
        if(!vis[v[i]]){
            bel[i+1>>1]=v[i];
            siz[v[i]]=1;
            is_root[v[i]]=1;
            val[v[i]]=totalval[v[i]]=w[i];
            fa[v[i]]=U;
            dfs(v[i]);
        }
    }
}
int main(){
    int op,x,y,z;
//  freopen("poj2763.in","r",stdin);
//  freopen("poj2763.out","w",stdout);
    scanf("%d%d%d",&n,&m,&cur);
    for(int i=1;i<n;++i){
        scanf("%d%d%d",&x,&y,&z);
        AddEdge(x,y,z);
        AddEdge(y,x,z);
    }
    siz[1]=1;
    is_root[1]=1;
    dfs(1);
    for(int i=1;i<=m;++i){
        scanf("%d%d",&op,&x);
        if(!op){
            Access(x);
            printf("%d
",Calc(x,cur));
            cur=x;
        }
        else{
            scanf("%d",&y);
            Splay(bel[x]);
            val[bel[x]]=y;
            Maintain(bel[x]);
        }
    }
    return 0;
}

<法二>

#include<cstdio>
#include<iostream>
#include<stack>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxn 200005
int fa[maxn],c[maxn][2],siz[maxn];
bool is_root[maxn],delta[maxn];
int val[maxn],totalval[maxn];
void Mark(int x){
    if(x){
        delta[x]^=1;
    }
}
void Maintain(int x)
{
    siz[x]=siz[c[x][0]]+siz[c[x][1]]+1;
    totalval[x]=totalval[c[x][0]]+totalval[c[x][1]]+val[x];
}
void pushdown(int x){
    if(delta[x]){
        Mark(c[x][0]);
        Mark(c[x][1]);
        swap(c[x][0],c[x][1]);
        delta[x]=0;
    }
}
void Rotate(int x,bool flag)
{
    int y=fa[x];
    c[y][!flag]=c[x][flag];
    if(c[x][flag]){
        fa[c[x][flag]]=y;
    }
    if(fa[y] && c[fa[y]][c[fa[y]][1]==y]==y){
        c[fa[y]][c[fa[y]][1]==y]=x;
    }
    fa[x]=fa[y];
    c[x][flag]=y;
    fa[y]=x;
    if(is_root[y]){
        is_root[y]=0;
        is_root[x]=1;
    }
    Maintain(y);
    Maintain(x);
}
stack<int>st;
void Splay(int x)
{
    pushdown(x);
    if(!x || is_root[x]){
        return;
    }
    int U=x;
    while(!is_root[U]){
        st.push(U);
        U=fa[U];
    }
    st.push(U);
    while(!st.empty()){
        pushdown(st.top());
        st.pop();
    }
    int y;
    while(y=fa[x],(!is_root[x])){
        if(is_root[y]){
            Rotate(x,c[y][0]==x);
        }
        else{
            if((c[y][0]==x)==(c[fa[y]][0]==y)){
                Rotate(y,c[fa[y]][0]==y);
            }
            else{
                Rotate(x,c[y][0]==x);
                y=fa[x];
            }
            Rotate(x,c[y][0]==x);
        }
    }
    Maintain(x);
}
void Access(int x){
    int y;
    Splay(x);
    while(fa[x]){
        y=fa[x];
        Splay(y);
        Splay(x);
        if(c[y][1]){
            is_root[c[y][1]]=1;
        }
        is_root[x]=0;
        c[y][1]=x;
        Splay(x);
    }
    if(c[x][1]){
        is_root[c[x][1]]=1;
        c[x][1]=0;
    }
}
void ChangeRoot(int x){
    Access(x);
    Splay(x);
    Mark(x);
}
int QSum(int U,int V){
    ChangeRoot(U);
    Access(V);
    Splay(V);
    return val[V]+totalval[c[V][0]];
}
int v[maxn<<1],nex[maxn<<1],first[maxn],w[maxn<<1],e;
void AddEdge(int U,int V,int W){
    v[++e]=V;
    w[e]=W;
    nex[e]=first[U];
    first[U]=e;
}
int tot,bel[maxn];
void dfs(int U){
    for(int i=first[U];i;i=nex[i]){
        if(!siz[v[i]]){
        	bel[i+1>>1]=++tot;
        	
    		siz[tot]=1;
    		is_root[tot]=1;
    		val[tot]=totalval[tot]=w[i];
            fa[tot]=U;
            
    		siz[v[i]]=1;
    		is_root[v[i]]=1;
    		val[v[i]]=totalval[v[i]]=0;
            fa[v[i]]=tot;
            
            dfs(v[i]);
        }
    }
}
int n,m,cur;
int main(){
	int op,x,y,z;
//	freopen("poj2763.in","r",stdin);
	scanf("%d%d%d",&n,&m,&cur);
	tot=n;
	for(int i=1;i<n;++i){
        scanf("%d%d%d",&x,&y,&z);
        AddEdge(x,y,z);
        AddEdge(y,x,z);
    }
    siz[1]=1;
    is_root[1]=1;
    dfs(1);
    for(int i=1;i<=m;++i){
        scanf("%d%d",&op,&x);
        if(!op){
            printf("%d
",QSum(x,cur));
            cur=x;
        }
        else{
            scanf("%d",&y);
            Splay(bel[x]);
            val[bel[x]]=y;
            Maintain(bel[x]);
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/autsky-jadek/p/7638667.html