树链剖分+线段树求和维护树上最大/最小值

//树链剖分,线段树维护
#include <iostream>
#include <cstdio>
#define maxn 300500
#define INF 0x3f3f3f3f
using namespace std;

int n,m;
int head[maxn],cnt;
int dep[maxn],son[maxn],siz[maxn],fa[maxn];
int top[maxn],seg[maxn],rnk[maxn],tot;
int maxx[maxn],sum[maxn];
int a[maxn];

char ch;

struct EDGE
{
    int next,to;
}edge[maxn];

void add(int u,int v)
{
    edge[++cnt].next=head[u];
    edge[cnt].to=v;
    head[u]=cnt;
}

void dfs1(int root)
{
    son[root]=0;
    siz[root]=1;
    for(int i=head[root];i;i=edge[i].next)
    {
        int v=edge[i].to;
        if(v==fa[root])continue;
        dep[v]=dep[root]+1;
        fa[v]=root;
        dfs1(v);
        if(siz[son[root]]<siz[v])son[root]=v;
        siz[root]+=siz[v];
    }
}

void dfs2(int root,int tp)
{
    top[root]=tp;seg[root]=++tot;rnk[tot]=root;
    if(son[root])dfs2(son[root],tp);
    for(int i=head[root];i;i=edge[i].next)
    {
        int v=edge[i].to;
        if(v==fa[root]||v==son[root])continue;
        dfs2(v,v);
    }
}

void build(int k,int l,int r)
{
    if(l==r)
    {
        maxx[k]=sum[k]=a[rnk[l]];
        return;
    }
    int mid=(l+r)>>1;
    build(k<<1,l,mid);
    build(k<<1|1,mid+1,r);
    sum[k]=sum[k<<1]+sum[k<<1|1];
    maxx[k]=max(maxx[k<<1],maxx[k<<1|1]);
}

void update(int k,int l,int r,int x,int v)
{
    if(l==r)
    {
        maxx[k]=sum[k]=v;
        return;
    }
    int mid=(l+r)>>1;
    if(x<=mid)update(k<<1,l,mid,x,v);
    else update(k<<1|1,mid+1,r,x,v);
    sum[k]=sum[k<<1]+sum[k<<1|1];
    maxx[k]=max(maxx[k<<1],maxx[k<<1|1]);
}

int querysum(int k,int l,int r,int x,int y)
{
    if(x<=l&&y>=r)
    {
        return sum[k];
    }
    int mid=(l+r)>>1;
    int res=0;
    if(x<=mid)res+=querysum(k<<1,l,mid,x,y);
    if(y>mid)res+=querysum(k<<1|1,mid+1,r,x,y);
    return res;
}

int querymax(int k,int l,int r,int x,int y)
{
    if(x<=l&&y>=r)
    {
        return maxx[k];
    }
    if(y<l||x>r)return -INF;
    int mid=(l+r)>>1;
    return max(querymax(k<<1,l,mid,x,y),querymax(k<<1|1,mid+1,r,x,y));
}

int query_Max_tree(int k,int l,int r,int u,int v)
{
    int fu=top[u],fv=top[v];
    int ans=-INF;
    while(fu!=fv)
    {
        if(dep[fu]<dep[fv])
        {
            swap(fu,fv);
            swap(u,v);
        }
        ans=max(ans,querymax(1,1,n,seg[fu],seg[u]));
        u=fa[fu];
        fu=top[u];
    }
    if(dep[u]<dep[v])swap(u,v);
    ans=max(ans,querymax(1,1,n,seg[v],seg[u]));
    return ans;
}

int query_Sum_tree(int k,int l,int r,int u,int v)
{
    int fu=top[u],fv=top[v];
    int ans=0;
    while(fu!=fv)
    {
        if(dep[fu]<dep[fv])
        {
            swap(fu,fv);
            swap(u,v);
        }
        ans+=querysum(1,1,n,seg[fu],seg[u]);
        u=fa[fu];
        fu=top[u];
    }
    if(dep[u]<dep[v])swap(u,v);
    ans+=querysum(1,1,n,seg[v],seg[u]);
    return ans;
}

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n-1;i++)
    {
        int u,v;
        scanf("%d%d",&u,&v);
        add(u,v);add(v,u);
    }
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    dep[1]=1;dfs1(1);dfs2(1,1);
    build(1,1,n);
    scanf("%d",&m);
    for(int i=1;i<=m;i++)
    {
        char op[10];
        int u,v;
        scanf("%s%d%d",op,&u,&v);
        if(op[0]=='C')update(1,1,n,seg[u],v);
        else if(op[1]=='M')printf("%d\n",query_Max_tree(1,1,n,u,v));
        else printf("%d\n",query_Sum_tree(1,1,n,u,v));
    }

    //ch=getchar();
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Bw-Orzzzzz/p/10829173.html