洛谷——P2590 [ZJOI2008]树的统计(树链剖分模板练手)

P2590 [ZJOI2008]树的统计

 

I. CHANGE u t : 把结点u的权值改为t

II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值

III. QSUM u v: 询问从点u到点v的路径上的节点的权值和

 

(博主)神蒟本蒻,又A了一道树链剖分的模板题,还是太颓废了。。。

调了我一个小时。。。

dfs+线段树维护区间和和最大值。

自带大常常数

#include<iostream>
#include<cstdio>
#include<cmath>

#define LL long long
#define IL inline
#define RE register
#define N 1000000
using namespace std;

int head[N],tot,n,m,val[N],val_w[N];
struct node{
    int to,next;
}e[N];

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

int f[N],siz[N],son[N],top[N],dep[N],id[N],item;

IL void dfs1(int u,int fa){
    f[u]=fa,siz[u]=1,dep[u]=dep[fa]+1;
    int maxson=-1;
    for(int i=head[u];i;i=e[i].next){
        int v=e[i].to;
        if(v==fa) continue;
        dfs1(v,u);
        siz[u]+=siz[v];
        if(siz[v]>maxson) maxson=siz[v],son[u]=v;
    }
}

IL void dfs2(int u,int topf){
    id[u]=++item,top[u]=topf,val_w[item]=val[u];
    if(!son[u]) return;
    dfs2(son[u],topf);
    for(int i=head[u];i;i=e[i].next){
        int v=e[i].to;
        if(v==f[u]||v==son[u]) continue;
        dfs2(v,v);
    }
}
struct Segment{
    int l,r,w,w_max;
}tr[N];

IL void push_up(int k){
    tr[k].w_max=max(tr[k<<1].w_max,tr[k<<1|1].w_max);
    tr[k].w=tr[k<<1].w+tr[k<<1|1].w;
}

IL void build(int k,int l,int r){
    tr[k].l=l,tr[k].r=r;
    if(l==r){tr[k].w=tr[k].w_max=val_w[l];return;}
    int mid=(l+r)>>1;
    build(k<<1,l,mid);
    build(k<<1|1,mid+1,r);
    push_up(k);
}

IL void change(int k,int X,int val_V){
    int l=tr[k].l,r=tr[k].r,mid=(l+r)>>1;
    if(l==r) {tr[k].w_max=tr[k].w=val_V;return;}
    if(X<=mid) change(k<<1,X,val_V);
    else change(k<<1|1,X,val_V);
    push_up(k);
}

IL int ask_max(int k,int ql,int qr){
    int l=tr[k].l,r=tr[k].r,mid=(l+r)>>1;
    if(l>=ql&&r<=qr) return tr[k].w_max;
    int ans=-0x7fffffff;
    if(ql<=mid) ans=ask_max(k<<1,ql,qr);
    if(qr>mid) ans=max(ans,ask_max(k<<1|1,ql,qr));
    return ans;
}

IL int ask_sum(int k,int ql,int qr){
    int l=tr[k].l,r=tr[k].r,mid=(l+r)>>1;
    if(l>=ql&&r<=qr) return tr[k].w;
    int ans=0;
    if(ql<=mid) ans+=ask_sum(k<<1,ql,qr);
    if(qr>mid) ans+=ask_sum(k<<1|1,ql,qr);
    return ans;
}

IL int q_max(int u,int v){
    int ans=-0x7fffffff;
    while(top[u]!=top[v]){
        if(dep[top[u]]<dep[top[v]]) swap(u,v);
        ans=max(ans,ask_max(1,id[top[u]],id[u]));
        u=f[top[u]];
    }
    if(dep[u]<dep[v]) swap(u,v);
    ans=max(ans,ask_max(1,id[v],id[u]));
    return ans;
}


IL int q_sum(int u,int v){
    int ans=0;
    while(top[u]!=top[v]){
        if(dep[top[u]]<dep[top[v]]) swap(u,v);
        ans+=ask_sum(1,id[top[u]],id[u]);
        u=f[top[u]];
    }
    if(dep[u]<dep[v]) swap(u,v);
    ans+=ask_sum(1,id[v],id[u]);
    return ans;
}

string s;

int main()
{
    scanf("%d",&n);
    for(int u,v,i=1;i<n;i++){
        scanf("%d%d",&u,&v);
        add(u,v),add(v,u);
    }
    for(int i=1;i<=n;i++) scanf("%d",&val[i]);
    dfs1(1,1);
    dfs2(1,1);
    build(1,1,n);
    scanf("%d",&m);    
    for(int u,v,i=1;i<=m;i++){
        cin>>s;
        scanf("%d%d",&u,&v);
        if(s=="CHANGE")
            change(1,id[u],v);
        else if(s=="QMAX") printf("%d\n",q_max(u,v));
        else printf("%d\n",q_sum(u,v));
    }
    
    return 0;
}

 

posted @ 2018-10-12 13:53  清风我已逝  阅读(145)  评论(2编辑  收藏  举报