zoukankan      html  css  js  c++  java
  • 【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;
    }
  • 相关阅读:
    菜根谭#219
    菜根谭#218
    菜根谭#217
    菜根谭#216
    有了OpenMP,MPI,为什么还要MapReduce? (转载)
    人生就是一场战略
    SDAccel 开发环境
    各种加速卡 异构计算
    Nvidia Tesla (GPGPU)系列发展流程
    Nvidia 架构发展
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/7638667.html
Copyright © 2011-2022 走看看