P2590 [ZJOI2008]树的统计(树链剖分)

Posted kafuuchino

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P2590 [ZJOI2008]树的统计(树链剖分)相关的知识,希望对你有一定的参考价值。

P2590 [ZJOI2008]树的统计

虽然是入门树剖模板

但是我终于1A了(大哭)

懒得写啥了(逃

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
inline int Max(int a,int b){return a>b?a:b;}
inline void Swap(int &a,int &b){a^=b^=a^=b;}
#define N 30005
int n,Q,Top[N],bgs[N],siz[N],fa[N],val[N];
int ID,id[N],tmp[N],sum[N<<2],mxd[N<<2];
int cnt,hd[N],nxt[N<<1],ed[N],poi[N<<1];
#define lc o<<1
#define rc o<<1|1
#define mid (l+r)/2
inline void adde(int x,int y){
    nxt[ed[x]]=++cnt; hd[x]=hd[x]?hd[x]:cnt;
    ed[x]=cnt; poi[cnt]=y;
}
inline void up(int o){
    sum[o]=sum[lc]+sum[rc];
    mxd[o]=Max(mxd[lc],mxd[rc]);
}
void build(int o,int l,int r){
    if(l==r){sum[o]=mxd[o]=tmp[l]; return ;}
    build(lc,l,mid); build(rc,mid+1,r); up(o);
}
void modi(int o,int l,int r,int x,int v){
    if(l==r){sum[o]=mxd[o]=v; return ;}
    if(x<=mid) modi(lc,l,mid,x,v);
    else modi(rc,mid+1,r,x,v);
    up(o);
}
int ask1(int o,int l,int r,int x1,int x2){
    if(x1<=l&&r<=x2) return mxd[o];
    int re=-1e9;
    if(x1<=mid) re=Max(re,ask1(lc,l,mid,x1,x2));
    if(x2>mid) re=Max(re,ask1(rc,mid+1,r,x1,x2));
    return re;
}
int ask2(int o,int l,int r,int x1,int x2){
    if(x1<=l&&r<=x2) return sum[o];
    int re=0;
    if(x1<=mid) re+=ask2(lc,l,mid,x1,x2);
    if(x2>mid) re+=ask2(rc,mid+1,r,x1,x2);
    return re;
}
void dfs1(int x,int Fa){
    fa[x]=Fa; siz[x]=1;
    for(int i=hd[x];i;i=nxt[i]){
        int to=poi[i];
        if(to==Fa) continue;
        dfs1(to,x);
        if(siz[to]>siz[bgs[x]]) bgs[x]=to;
        siz[x]+=siz[to];
    }
}
void dfs2(int x,int tp){
    tmp[id[x]=++ID]=val[x]; Top[x]=tp;
    if(bgs[x]) dfs2(bgs[x],tp);
    for(int i=hd[x];i;i=nxt[i]){
        int to=poi[i];
        if(to==fa[x]||to==bgs[x]) continue;
        dfs2(to,to);
    }
}
int Amax(int x,int y){
    int re=-1e9;
    for(;Top[x]!=Top[y];x=fa[Top[x]]){
        if(id[Top[x]]<id[Top[y]]) Swap(x,y);
        re=Max(re,ask1(1,1,n,id[Top[x]],id[x]));
    }if(id[x]>id[y]) Swap(x,y);
    return Max(re,ask1(1,1,n,id[x],id[y]));
}
int Asum(int x,int y){
    int re=0;
    for(;Top[x]!=Top[y];x=fa[Top[x]]){
        if(id[Top[x]]<id[Top[y]]) Swap(x,y);
        re+=ask2(1,1,n,id[Top[x]],id[x]);
    }if(id[x]>id[y]) Swap(x,y);
    return re+ask2(1,1,n,id[x],id[y]);
}
int main(){
    scanf("%d",&n); int q1,q2; char opt[9];
    for(int i=1;i<n;++i)
        scanf("%d%d",&q1,&q2),adde(q1,q2),adde(q2,q1);
    for(int i=1;i<=n;++i) scanf("%d",&val[i]);
    dfs1(1,0); dfs2(1,1);build(1,1,n);
    scanf("%d",&Q);
    while(Q--){
        scanf("%s%d%d",opt,&q1,&q2);
        if(opt[1]==H) modi(1,1,n,id[q1],q2);
        else if(opt[1]==M) printf("%d
",Amax(q1,q2));
        else if(opt[1]==S) printf("%d
",Asum(q1,q2));
    }return 0;
}

 

以上是关于P2590 [ZJOI2008]树的统计(树链剖分)的主要内容,如果未能解决你的问题,请参考以下文章

P2590 [ZJOI2008]树的统计

BZOJ 1036 [ZJOI2008]树的统计Count (树链剖分 - 点权剖分 - 单点权修改)

bzoj 1036 [ZJOI2008]树的统计Count(树链剖分,线段树)

1036: [ZJOI2008]树的统计Count(树链剖分)

luoguP2590 [ZJOI2008]树的统计(树链剖分)

[ZJOI2008]树的统计-树链剖分