树的统计

开两个线段树,一个维护和,一个维护最大值。

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int maxn=300000+100;
int n,q;
int beg[maxn],nex[maxn],to[maxn],e;
inline void add(int x,int y){
    e++;nex[e]=beg[x];
    beg[x]=e;to[e]=y;
}
int val[maxn];
int f[maxn],son[maxn],size[maxn],dep[maxn];
inline void dfs1(int x,int fa){
    f[x]=fa;
    dep[x]=dep[fa]+1;
    size[x]=1;
    for(int i=beg[x];i;i=nex[i]){
        int t=to[i];
        if(t==fa)continue;
        dfs1(t,x);
        size[x]+=size[t];
        if(size[t]>size[son[x]])son[x]=t;
    }
}
int id[maxn],num[maxn],top[maxn],cnt;
inline void dfs2(int x,int topc){
    id[x]=++cnt;
    num[cnt]=val[x];
    top[x]=topc;
    if(!son[x])return;
    dfs2(son[x],topc);
    for(int i=beg[x];i;i=nex[i]){
        int t=to[i];
        if(t==f[x]||t==son[x])continue;
        dfs2(t,t);
    }
}
int tsum[maxn],tmax[maxn];
inline void build(int h,int l,int r){
    if(l==r){
        tsum[h]=tmax[h]=num[l];
        return;
    }
    int mid=(l+r)>>1;
    build(h<<1,l,mid);
    build(h<<1|1,mid+1,r);
    tsum[h]=tsum[h<<1]+tsum[h<<1|1];
    tmax[h]=max(tmax[h<<1],tmax[h<<1|1]);
}
inline void update(int h,int l,int r,int pos,int val1){
    if(l==r){
        tsum[h]=tmax[h]=val1;
        return;
    }
    int mid=(l+r)>>1;
    if(mid>=pos)update(h<<1,l,mid,pos,val1);
    else update(h<<1|1,mid+1,r,pos,val1);
    tsum[h]=tsum[h<<1]+tsum[h<<1|1];
    tmax[h]=max(tmax[h<<1],tmax[h<<1|1]);
}
inline int querymax(int h,int l,int r,int x,int y){
    if(l>y||r<x)return -1e15;
    if(l>=x&&r<=y)return tmax[h];
    int mid=(l+r)>>1;
    return max(querymax(h<<1,l,mid,x,y),querymax(h<<1|1,mid+1,r,x,y));
}
inline int Qmax(int x,int y){
    int ans=-1e15;
    while(top[x]!=top[y]){
        if(dep[top[x]]<dep[top[y]])swap(x,y);
        ans=max(ans,querymax(1,1,n,id[top[x]],id[x]));
        x=f[top[x]];
    }
    if(dep[x]>dep[y])swap(x,y);
    ans=max(ans,querymax(1,1,n,id[x],id[y]));
    return ans;
}
inline int querysum(int h,int l,int r,int x,int y){
    if(l>y||r<x)return 0;
    if(l>=x&&r<=y)return tsum[h];
    int mid=(l+r)>>1;
    return querysum(h<<1,l,mid,x,y)+querysum(h<<1|1,mid+1,r,x,y);
}
inline int Qsum(int x,int y){
    int ans=0;
    while(top[x]!=top[y]){
        if(dep[top[x]]<dep[top[y]])swap(x,y);
        ans+=querysum(1,1,n,id[top[x]],id[x]);
        x=f[top[x]];
    }
    if(dep[x]>dep[y])swap(x,y);
    ans+=querysum(1,1,n,id[x],id[y]);
    return ans;
}
signed main(){
    //freopen("tree.in","r",stdin);
    cin>>n;
    int x,y;
    for(int i=1;i<n;i++){
        scanf("%lld%lld",&x,&y);
        add(x,y);add(y,x);
    }
    for(int i=1;i<=n;i++)
        scanf("%lld",&val[i]);
    dfs1(1,0);
    dfs2(1,1);
    build(1,1,n);
    cin>>q;
    string opt;
    for(int i=1;i<=q;i++){
        cin>>opt;
        if(opt=="CHANGE"){
            scanf("%lld%lld",&x,&y);
            update(1,1,n,id[x],y);
        }else if(opt=="QMAX"){
            scanf("%lld%lld",&x,&y);
            printf("%lld
",Qmax(x,y));
        }else{
            scanf("%lld%lld",&x,&y);
            printf("%lld
",Qsum(x,y));
        }
    }
    return 0;
} 

深深地感到自己的弱小。

原文地址:https://www.cnblogs.com/syzf2222/p/12386707.html