hdu 5052 Yaoge’s maximum profit

有n个节点的树,有q次操作,每次操作选择一条路径问从起点出发到终点可以在任意点花vi买入一个商品并在之后任意一点以vj卖掉。

问最大收益是多少,并在每次操作后将那条路径所有点权加上v。

 

树链剖分将问题变为直线上的问题后,考虑用线段树维护一个最大值与最小值,以及从直线左到右的最大收益以及直线右到左的最大收益。

在区间合并时,最大收益可能时两个子区间最大收益的max,也可能是左区间的最小值与右区间最大值的差值。

pushdown的时候只需要把最大值最小值+v即可,因为都加上v对收益没有影响。

最后查询的时候线段树合并即可,注意左右两条链还可能产生差值影响答案。

 

 

#include <bits/stdc++.h>
#define Lson l,mid,rt<<1
#define Rson mid+1,r,rt<<1|1
using namespace std;
const int M = 1e5+7;
int _,n,q,a[M];
int head[M],cnt,tot,tmp;
int sz[M],f[M],son[M],dep[M],rnk[M],id[M],top[M];
struct edge
{
    int v,next;
}e[M<<1];
struct Tree{
    int mx,mn,rpro,lpro;
    int lazy;
}tree[M<<3];
void init(){
    tot=cnt=0;memset(head,-1,sizeof(head));
}
/**************************找重儿子****************************/
void add(int u,int v){
    e[++cnt].v=v;e[cnt].next=head[u];
    head[u]=cnt;
}
void dfs(int u,int fa,int d){
    sz[u]=1,son[u]=-1,f[u]=fa,dep[u]=d;
    for(int i=head[u];~i;i=e[i].next){
        int v=e[i].v;
        if(v==fa) continue;
        dfs(v,u,d+1);
        sz[u]+=sz[v];
        if(son[u]==-1||sz[v]>sz[son[u]]) son[u]=v;
    }
    return ;
}
void dfs1(int u,int t){
    id[u]=++tot;
    rnk[tot]=u;
    top[u]=t;
    if(son[u]==-1) return;
    dfs1(son[u],t);
    for(int i=head[u];~i;i=e[i].next){
        int v=e[i].v;
        if(v==f[u]||v==son[u]) continue;
        dfs1(v,v);
    }
    return ;
}
/**************************线段树****************************/
void Pushup(int rt,int l,int r){
    tree[rt].mn=min(tree[l].mn,tree[r].mn);
    tree[rt].mx=max(tree[l].mx,tree[r].mx);
    tree[rt].rpro=max(tree[l].rpro,tree[r].rpro);//从左到右的最大收益
    tree[rt].lpro=max(tree[l].lpro,tree[r].lpro);//从右到左
    if(tree[l].mn<tree[r].mx){
        tree[rt].rpro=max(tree[rt].rpro,tree[r].mx-tree[l].mn);
    }
    if(tree[l].mx>tree[r].mn){
        tree[rt].lpro=max(tree[rt].lpro,tree[l].mx-tree[r].mn);
    }
}
void Pushdown(int rt,int l,int r){
    if(tree[rt].lazy){//区间都+v对收益没影响
        int v=tree[rt].lazy;
        tree[rt].lazy=0;
        tree[l].lazy+=v;
        tree[r].lazy+=v;
        tree[l].mx+=v;tree[l].mn+=v;
        tree[r].mx+=v;tree[r].mn+=v;//把mx写成了mn调了半个小时shit
    }
}
void build(int l,int r,int rt){
    tree[rt].lazy=0;
    if(l==r){
        //cout<<l<<" gg "<<rnk[l]<<" rt"<<rt<<endl;
        tree[rt].mn=tree[rt].mx=a[rnk[l]];
        tree[rt].rpro=tree[rt].lpro=0;
        return ;
    }
    int mid=(l+r)>>1;
    build(Lson);
    build(Rson);
    Pushup(rt,rt<<1,rt<<1|1);
    //cout<<l<<" "<<r<<" "<<tree[rt].lpro<<" "<<tree[rt].rpro<<" "<<tree[rt].mx<<" "<<tree[rt].mn<<endl;
}
void update(int L,int R,int l,int r,int rt,int v){
    if(L<=l&&r<=R){
        tree[rt].lazy+=v;
        tree[rt].mx+=v;tree[rt].mn+=v;
        return ;
    }
    Pushdown(rt,rt<<1,rt<<1|1);
    int mid=(l+r)>>1;
    if(L<=mid) update(L,R,Lson,v);
    if(R>mid) update(L,R,Rson,v);
    Pushup(rt,rt<<1,rt<<1|1);
    //cout<<l<<" "<<r<<" "<<tree[rt].lpro<<" "<<tree[rt].rpro<<" "<<tree[rt].mx<<" "<<tree[rt].mn<<endl;
}
int query(int L,int R,int l,int r,int rt){
    if(L==l&&R==r){
        return rt;
    }
    Pushdown(rt,rt<<1,rt<<1|1);
    int mid=(l+r)>>1,res;
    if(L>mid){
        res=query(L,R,Rson);
        //Pushup(rt,rt<<1,rt<<1|1);
        return res;
    }
    else if(R<=mid){
        res=query(L,R,Lson);
        //Pushup(rt,rt<<1,rt<<1|1);
        return res;
    }
    else{
        int ll=query(L,mid,Lson),rr=query(mid+1,R,Rson);
        Pushup(++tmp,ll,rr);
        return tmp;
    }
}
/**************************剖分****************************/
void updates(int x,int y,int v){
    int fx=top[x],fy=top[y];
    while(fx!=fy){
        if(dep[fx]>dep[fy]){
            update(id[fx],id[x],1,n,1,v);
            x=f[fx],fx=top[x];
        }
        else{
            update(id[fy],id[y],1,n,1,v);
            y=f[fy],fy=top[y];
        }
    }
    if(dep[x]<dep[y])
        update(id[x],id[y],1,n,1,v);
    else
        update(id[y],id[x],1,n,1,v);
}
int sum(int x,int y){
    //cout<<"1:"<<tree[8].mn<<" "<<tree[8].mx<<endl;
    int fx=top[x],fy=top[y];
    int xl,xr=-1,yl,yr=-1;tmp=M<<2;
    while(fx!=fy){
        if(dep[fx]>dep[fy]){
            xl=query(id[fx],id[x],1,n,1);
            if(xr==-1) xr=xl;
            else{
                Pushup(++tmp,xl,xr);xr=tmp;
            }
            x=f[fx],fx=top[x];
        }
        else{
            yl=query(id[fy],id[y],1,n,1);
            if(yr==-1) yr=yl;
            else{
                Pushup(++tmp,yl,yr);yr=tmp;
            }
            y=f[fy],fy=top[y];
        }
    }
    if(dep[x]<dep[y]){
        yl=query(id[x],id[y],1,n,1);
        if(yr==-1) yr=yl;
        else{
            Pushup(++tmp,yl,yr);yr=tmp;
        }
    }
    else{
        xl=query(id[y],id[x],1,n,1);
        if(xr==-1) xr=xl;
        else{
            Pushup(++tmp,xl,xr);xr=tmp;
        }
    }
    //cout<<"xr:"<<xr<<endl;
    if(yr==-1) return tree[xr].lpro;
    if(xr==-1) return tree[yr].rpro;
    int res;
    res=max(tree[xr].lpro,tree[yr].rpro);//左右两条链的答案
    if(tree[xr].mn<tree[yr].mx){//左右两条链还有可能产生答案
        res=max(res,tree[yr].mx-tree[xr].mn);
    }
    return res;
}
int main(){
    scanf("%d",&_);
    while(_--){
        init();
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        for(int i=1;i<n;i++){
            int from,to;
            scanf("%d%d",&from,&to);
            add(from,to);add(to,from);
        }
        dfs(1,-1,1);dfs1(1,1);
        build(1,n,1);
        scanf("%d",&q);
        while(q--){
            int from,to,v;
            scanf("%d%d%d",&from,&to,&v);
            printf("%d\n",sum(from,to));
            updates(from,to,v);
        }
    }
    return 0;
}
View Code

 

posted @ 2018-08-29 14:33  LMissher  阅读(153)  评论(0编辑  收藏  举报