hdu 5052 Yaoge’s maximum profit 树链剖分 2014 ACM/ICPC Asia Regional Shanghai Online

来源:互联网 发布:三国志9pk优化补丁版 编辑:程序博客网 时间:2024/06/05 05:55

题意:

给定n个点构成的树,每个点都有点权。

下面n行给出每个点点权表示每个点买卖鸡腿的价格

下面n-1行给出树边

下面Q个操作

Q行

u, v, val

从u走到v,过程中可以买一个鸡腿,然后到后面卖掉,输出max(0, 最大的收益)

然后给[u,v]路径上点点权+=x

思路:树链剖分,做过bzoj2243后基本上稍微想下就会有思路。线段树中需要维护区间最大值Max,区间最小值Min,懒惰标记tag,

区间沿正方向可获得的最大利润ans1,区间沿反方向可获得的最大利润ans2。在solve中需要记录上次剖分结果,根据方向决定是更新

minl(正向更新minl)还是maxr(反向更新maxr),以及要知道当前剖分区间的最大值Max和最小值Min,通过这些值不断更新ans。详

见代码:

/*********************************************************  file name: hdu5052.cpp  author : kereo  create time:  2015年01月26日 星期一 13时13分26秒*********************************************************/#include<iostream>#include<cstdio>#include<cstring>#include<queue>#include<set>#include<map>#include<vector>#include<stack>#include<cmath>#include<string>#include<algorithm>using namespace std;typedef long long ll;const int sigma_size=26;const int N=100+50;const int MAXN=50000+50;const int inf=0x3fffffff;const double eps=1e-8;const int mod=100000000+7;#define L(x) (x<<1)#define R(x) (x<<1|1)#define PII pair<int, int>#define mk(x,y) make_pair((x),(y))int n,m,edge_cnt,cnt;int head[MAXN],sz[MAXN],fa[MAXN],son[MAXN],top[MAXN],dep[MAXN],pos[MAXN],a[MAXN];struct Edge{    int v,next;}edge[MAXN<<1];struct node{    int l,r;    int Min,Max,tag,ans1,ans2; //ans1表示沿正方向(->)的最大profit,ans2表示沿着反方向的最大profit}segtree[MAXN<<2];void init(){    edge_cnt=cnt=0;    memset(head,-1,sizeof(head));}void addedge(int u,int v){    edge[edge_cnt].v=v;    edge[edge_cnt].next=head[u]; head[u]=edge_cnt++;}void dfs1(int u,int pre,int depth){    sz[u]=1; fa[u]=pre; son[u]=0; dep[u]=depth;    for(int i=head[u];i!=-1;i=edge[i].next){        int v=edge[i].v;        if(v == pre)            continue;        dfs1(v,u,depth+1);        sz[u]+=sz[v];        if(sz[son[u]]<sz[v])            son[u]=v;    }}void dfs2(int u,int tp){    pos[u]=++cnt; top[u]=tp;    if(son[u]!=0)         dfs2(son[u],top[u]);    for(int i=head[u];i!=-1;i=edge[i].next){        int v=edge[i].v;        if(v == fa[u] || v == son[u])            continue;        dfs2(v,v);    }}void push_down(int rt){    if(segtree[rt].tag){        segtree[L(rt)].tag+=segtree[rt].tag;        segtree[L(rt)].Max+=segtree[rt].tag; segtree[L(rt)].Min+=segtree[rt].tag;        segtree[R(rt)].tag+=segtree[rt].tag;        segtree[R(rt)].Max+=segtree[rt].tag; segtree[R(rt)].Min+=segtree[rt].tag;        segtree[rt].tag=0;    }}void push_up(int rt){    segtree[rt].Min=min(segtree[L(rt)].Min,segtree[R(rt)].Min);    segtree[rt].Max=max(segtree[L(rt)].Max,segtree[R(rt)].Max);    segtree[rt].ans1=max(segtree[R(rt)].Max-segtree[L(rt)].Min,max(segtree[L(rt)].ans1,segtree[R(rt)].ans1));    segtree[rt].ans2=max(segtree[L(rt)].Max-segtree[R(rt)].Min,max(segtree[L(rt)].ans2,segtree[R(rt)].ans2));}void build(int rt,int l,int r){    segtree[rt].l=l; segtree[rt].r=r;     segtree[rt].Max=segtree[rt].Min=0;    segtree[rt].tag=segtree[rt].ans1=segtree[rt].ans2=0;    if(l == r)        return ;    int mid=(l+r)>>1;    build(L(rt),l,mid); build(R(rt),mid+1,r);}void update(int rt,int l,int r,int x){    if(segtree[rt].l == l && segtree[rt].r == r){        segtree[rt].tag+=x;        segtree[rt].Max+=x; segtree[rt].Min+=x;        return ;    }    push_down(rt);    int mid=(segtree[rt].l+segtree[rt].r)>>1;    if(r<=mid)        update(L(rt),l,r,x);    else if(l>mid)        update(R(rt),l,r,x);    else{        update(L(rt),l,mid,x); update(R(rt),mid+1,r,x);    }    push_up(rt);}int query(int rt,int l,int r,int id,int &Max,int &Min){    if(segtree[rt].l == l && segtree[rt].r == r){        Max=segtree[rt].Max; Min=segtree[rt].Min;        if(id == 1)            return segtree[rt].ans1;        else             return segtree[rt].ans2;    }    push_down(rt);    int mid=(segtree[rt].l+segtree[rt].r)>>1;    if(r<=mid)        return query(L(rt),l,r,id,Max,Min);    else if(l>mid)        return query(R(rt),l,r,id,Max,Min);    else{        int minl=0,maxl=0,minr=0,maxr=0,ans;        ans=max(query(L(rt),l,mid,id,maxl,minl),query(R(rt),mid+1,r,id,maxr,minr));        Max=max(maxl,maxr); Min=min(minl,minr);        if(id == 1)            ans=max(ans,maxr-minl);        else             ans=max(ans,maxl-minr);        return ans;    }    push_up(rt);}int solve(int u,int v,int id,int w){ //从u到v    int ans=0;    if(id == 0){        int Max=-inf,Min=inf,minl=inf,maxr=-inf;        while(top[u]!=top[v]){            if(dep[top[u]]>dep[top[v]]){                ans=max(ans,query(1,pos[top[u]],pos[u],2,Max,Min));                ans=max(ans,Max-minl);                minl=min(minl,Min);                u=fa[top[u]];            }            else{                ans=max(ans,query(1,pos[top[v]],pos[v],1,Max,Min));                ans=max(ans,maxr-Min);                maxr=max(maxr,Max);                v=fa[top[v]];            }        }        //printf("u=%d v=%d\n",u,v);        if(dep[u]<dep[v])            ans=max(ans,query(1,pos[u],pos[v],1,Max,Min));        else             ans=max(ans,query(1,pos[v],pos[u],2,Max,Min));        //printf("ans=%d Min=%d Max=%d minl=%d maxr=%d\n",ans,Min,Max,minl,maxr);        ans=max(ans,Max-minl);        ans=max(ans,maxr-Min);        ans=max(ans,maxr-minl); //一开始漏了。。        //printf("-------------------------------\n");    }    else {        while(top[u]!=top[v]){            if(dep[top[u]]<dep[top[v]])                swap(u,v);            update(1,pos[top[u]],pos[u],w);            u=fa[top[u]];        }        if(dep[u]>dep[v])            swap(u,v);        update(1,pos[u],pos[v],w);    }    return ans;}int main(){    int T;    //freopen("in.txt","r",stdin);    scanf("%d",&T);    while(T--){        init();        scanf("%d",&n);        for(int i=1;i<=n;i++)            scanf("%d",&a[i]);        for(int i=1;i<n;i++){            int u,v;            scanf("%d%d",&u,&v);            addedge(u,v); addedge(v,u);        }        dfs1(1,1,1); dfs2(1,1); build(1,1,n);        /*for(int i=1;i<=n;i++)            printf("pos[%d]=%d top[%d]=%d\n",i,pos[i],i,top[i]);        printf("-------------------------------------\n");*/        for(int i=1;i<=n;i++)            update(1,pos[i],pos[i],a[i]);        scanf("%d",&m);        while(m--){            int u,v,w;            scanf("%d%d%d",&u,&v,&w);            int ans=solve(u,v,0,0); solve(u,v,1,w);            printf("%d\n",ans);        }    }return 0;}

0 0
原创粉丝点击