• 树的统计


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

    #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;
    } 

    深深地感到自己的弱小。

  • 相关阅读:
    python mysql操作
    常用sql语句总结
    python 正则表达式总结
    hdu 6199 dp
    hdu 6212 区间dp
    hdu 6214 割边最少的最小割
    2017沈阳网络赛G XOR 分块(分类讨论sqrt)
    HDU 6166 二进制分组
    hdu 6194 后缀数组
    hdu 6201 树分治
  • 原文地址:https://www.cnblogs.com/syzf2222/p/12386707.html
Copyright © 2020-2023  润新知