hdu 3966 LCT

題意:給定樹和樹上每一個節點的權值 操作是修改一條路徑上所有點的權值 

然後詢問點的權值是多少  

解法:這一題初看的時候想到用splay解 但是用lct應該是更加簡單的 

熟練剖分的話也可以的 因爲樹形沒有一點改變 然後用lct的時候其實就是在splay上打懶惰標記 這樣子我寫完之後就帶來了一個問題 那就是在這種情況下 我們執行access操作的時候是從該節點往上的 這樣子上一次的標記就不能下傳下來 然後我思考了一種暴力的方法 那就是在訪問一個節點的時候預先將其路徑上的根找到 然後我們進行標記的下傳就可以了

然後正解應該也是這個  

這讓我想起了以前所寫的splay 大多都是有find操作的 這種情況下 也是自頂向下進行的更新  那麼對於直接能夠找到節點的元素 我們是不是也應該採用這種方法進行更新呢 但是這樣一來 我們所依賴的大概就是splay的旋轉來進行神奇的複雜度平衡了 如果把它當作一顆平衡樹來看的話 的卻應該是這樣的(事實上 splay的卻是一顆平衡樹)

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
#define ls ch[rt][0]
#define rs ch[rt][1]
#define maxn 55555
int ch[maxn][2],fa[maxn],_rt[maxn],val[maxn],add[maxn];
inline void down(int rt){
    if(add[rt]){
        if(ls)val[ls]+=add[rt],add[ls]+=add[rt];
        if(rs)val[rs]+=add[rt],add[rs]+=add[rt];
        add[rt]=0;
    }
}
inline void _vis(int rt){
    if(!_rt[rt])_vis(fa[rt]);
    down(rt);
}
inline void rot(int rt){
    int f=fa[rt],side=ch[f][1]==rt,ll=ch[rt][!side];
    fa[ll]=f,ch[f][side]=ll;
    fa[rt]=fa[f];
    if(_rt[f])_rt[rt]=1,_rt[f]=0;
    else ch[fa[f]][ch[fa[f]][1]==f]=rt;
    fa[f]=rt,ch[rt][!side]=f;
}
inline void splay(int rt){
    _vis(rt);
    while(!_rt[rt]){
        down(rt);
        int f=fa[rt],ff=fa[f];
        if(_rt[f])rot(rt);
        else if((ch[f][1]==rt)==(ch[ff][1]==f))rot(f),rot(rt);
        else rot(rt),rot(rt);
    }
}
inline int ace(int rt){
    int y=0;
    for(;rt;y=rt,rt=fa[rt]){
        splay(rt);
        _rt[rs]=1,rs=y,_rt[rs]=0;
    }return y;
}
inline void lca(int &u,int &v){
    ace(v);v=0;
    for(;u;v=u,u=fa[u]){
        splay(u);
        if(!fa[u])return ;
        _rt[ch[u][1]]=1,ch[u][1]=v,_rt[v]=0;
    }
}
inline void ins(int u,int v,int w){
    lca(u,v);
    val[u]+=w;
    if(ch[u][1])val[ch[u][1]]+=w,add[ch[u][1]]+=w;
    val[v]+=w,add[v]+=w;
}

char op[111];
int a,b,c,u,v,n,m,tot,head[maxn];
struct edge{int v,next;}e[maxn<<1];
inline void init(){memset(head,-1,sizeof head);tot=0;}
inline void adde(int u,int v){
    e[tot].next=head[u];head[u]=tot,e[tot].v=v;
    ++tot;
}
void dfs(int u,int f){
    for(int i=head[u];i!=-1;i=e[i].next){
        int v=e[i].v;
        if(v==f)continue;
        fa[v]=u;
        dfs(v,u);
    }
}
int main(){
    while(~scanf("%d%d%d",&n,&a,&m)){
        
        for(int i=1;i<=n;++i)scanf("%d",&val[i]);
        init();
        for(int i=1;i<n;++i){
            scanf("%d%d",&u,&v);
            adde(u,v);adde(v,u);
        }
        for(int rt=0;rt<=n;++rt){
            add[rt]=fa[rt]=ls=rs=0;_rt[rt]=1;
        }dfs(1,-1);
        val[0]=0;
        
        while(m--){
            scanf("%s%d",op,&a);
            if(*op=='Q'){
                ace(a),printf("%d\n",val[a]);}
            else{
                scanf("%d%d",&b,&c);
                if(*op=='D')c=-c;
                ins(a,b,c);
            }
        }
        
    }
    return 0;
}

 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章