用动态树强弄树的统计

Description

 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。
  我们将以下面的形式来要求你对这棵树完成一些操作:
  I. CHANGE u t : 把结点u的权值改为t
  II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值
  III. QSUM u v: 询问从点u到点v的路径上的节点的权值和
  注意:从点u到点v的路径上的节点包括u和v本身

Solution

树的统计都是大家学习树链剖分时候的基础模板题。
现在刚学了一下Link_Cut_Tree(动态树的一种),强制把这题在做了做。就像当时用splay来强弄最大值,排序这些题目一样。
都是些基础的询问,不过让我涉及了一下lct的基础知识,只用到access和splay的基本操作。
离掌握lct还有一段路……

Code

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define rep(i,a) for(i=first[a];i;i=next[i])
using namespace std;
const int maxn=30007;
int i,j,k,l,n,m,ans;
int first[maxn*2],next[maxn*2],last[maxn*2],num,lca;
int pfa[maxn],t[maxn][2],key[maxn],mx[maxn],sum[maxn],f[maxn],deep[maxn];
char s[10];
void add(int x,int y){
    last[++num]=y;next[num]=first[x];first[x]=num;
    last[++num]=x;next[num]=first[y];first[y]=num;
}
void update(int x){
    mx[x]=max(key[x],max(mx[t[x][0]],mx[t[x][1]]));
    sum[x]=key[x]+sum[t[x][0]]+sum[t[x][1]];
}
bool son(int x){
    if(t[f[x]][0]==x)return 0;return 1;
}
void rotate(int x){
    int y=f[x],z=son(x);
    t[y][z]=t[x][1-z];
    if(t[x][1-z])f[t[x][1-z]]=y;f[x]=f[y];
    if(f[x])t[f[x]][son(y)]=x;
    else pfa[x]=pfa[y],pfa[y]=0;
    t[x][1-z]=y;f[y]=x;
    update(y);update(x);
}
void splay(int x){
    while(f[x]){
        if(f[f[x]])if(son(f[x])==son(x))rotate(f[x]);else rotate(x);
        rotate(x);
    }
}
void access(int x){
    int y=0;
    while(x){
        splay(x);
        f[t[x][1]]=0,pfa[t[x][1]]=x;
        t[x][1]=y,f[y]=x;
        pfa[y]=0;
        update(x);
        y=x,x=pfa[x];
    }lca=y;
}
void build(int x,int y){
    access(x);splay(x);pfa[x]=y;
}
void dfs(int x,int y){
    int i;deep[x]=deep[y]+1;
    rep(i,x)if(last[i]!=y)build(last[i],x),dfs(last[i],x);
}
int main(){
    scanf("%d",&n);key[0]=mx[0]=-0x7fffffff;
    fo(i,1,n-1)scanf("%d%d",&k,&l),add(k,l);
    fo(i,1,n)scanf("%d",&key[i]);
    dfs(1,0);
    scanf("%d",&m);
    fo(i,1,m){
        scanf("%s%d%d",s,&k,&l);
        if(s[0]=='Q'){
            if(k==l){printf("%d\n",key[k]);continue;}   
            if(deep[k]<deep[l])swap(k,l);
            access(k);access(l);splay(k);
            if(s[1]=='M'){
                ans=mx[k];
                if(lca==l)ans=max(ans,key[l]);
                else ans=max(ans,max(mx[t[lca][1]],key[lca]));
            }
            else{
                ans=sum[k];
                if(lca==l)ans+=key[l];
                else ans+=sum[t[lca][1]]+key[lca];
            }
            printf("%d\n",ans);
        }
        else{
            access(k);key[k]=l;splay(k);update(k);
        }
    }
}

你可能感兴趣的:(动态树,splay,LCT,树的统计,LinkCutTre)