HDU5692 Snacks

HDU5692 Snacks

Problem Description

百度科技园内有n个零食机,零食机之间通过n−1条路相互连通。每个零食机都有一个值v,表示为小度熊提供零食的价值。

由于零食被频繁的消耗和补充,零食机的价值v会时常发生变化。小度熊只能从编号为0的零食机出发,并且每个零食机至多经过一次。另外,小度熊会对某个零食机的零食有所偏爱,要求路线上必须有那个零食机。

为小度熊规划一个路线,使得路线上的价值总和最大。

Input

输入数据第一行是一个整数T(T≤10),表示有T组测试数据。

对于每组数据,包含两个整数n,m(1≤n,m≤100000),表示有n个零食机,m次操作。

接下来n−1行,每行两个整数x和y(0≤x,y<n),表示编号为x的零食机与编号为y的零食机相连。

接下来一行由n个数组成,表示从编号为0到编号为n−1的零食机的初始价值v(|v|<100000)。

接下来m行,有两种操作:0 x y,表示编号为x的零食机的价值变为y;1 x,表示询问从编号为0的零食机出发,必须经过编号为x零食机的路线中,价值总和的最大值。

本题可能栈溢出,辛苦同学们提交语言选择c++,并在代码的第一行加上:

`#pragma comment(linker, "/STACK:1024000000,1024000000") `

Output

对于每组数据,首先输出一行”Case #?:”,在问号处应填入当前数据的组数,组数从1开始计算。

对于每次询问,输出从编号为0的零食机出发,必须经过编号为x零食机的路线中,价值总和的最大值。

Sample Input

1

6 5

0 1

1 2

0 3

3 4

5 3

7 -5 100 20 -5 -7

1 1

1 3

0 2 -1

1 1

1 5

Sample Output

Case #1:

102

27

2

20

题解:

dfs序+线段树

题目要求修改点值和从0出发经过s点的最大权值和。

实质是求s点的子树中dis最大的,因为某一子树dfs序是连续的,所以该问题成了区间求最大值和区间修改。

修改某个点等价于将以这个点为根的最大值加上一个数。

代码:WA的..没调完...

WA的原因

1、修改错点了,应该是价值改,我改的价值的累加和....

2、修改完区间后...点没修改...

3、没用long long

4、md目前还是WA的。

#pragma comment(linker, "/STACK:1024000000,1024000000") 
#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 200002
using namespace std;
int t,n,m,od,sumedge,tim_node,kis,cnt;
int head[maxn],bf[maxn],l[maxn],r[maxn];
long long dis[maxn],ans[maxn],sum[maxn];

struct TREE{
    int l,r;
    long long maxx,s;
}tr[maxn<<2];

struct Edge{
    int x,y,nxt;
    Edge(int x=0,int y=0,int nxt=0):
        x(x),y(y),nxt(nxt){}
}edge[maxn<<1];

inline void add(int x,int y){
    edge[++sumedge]=Edge(x,y,head[x]);
    head[x]=sumedge;
}

void dfs(int x,int fa){
    bf[tim_node]=x;l[x]=tim_node++;
    for(int i=head[x];i;i=edge[i].nxt){
        int v=edge[i].y;
        if(v==fa)continue;
        dis[v]+=dis[x];
        dfs(v,x);
    }
    r[x]=tim_node-1;
}

inline void pushup(int p){
    tr[p].maxx=max(tr[p<<1].maxx,tr[p<<1|1].maxx);
}

inline void pushdown(int rt){
    if(tr[rt].s==0)return;
    tr[rt<<1].s+=tr[rt].s;tr[rt<<1|1].s+=tr[rt].s;
    tr[rt<<1].maxx+=tr[rt].s;tr[rt<<1|1].maxx+=tr[rt].s;
    tr[rt].s=0;
}

void build(int rt,int l,int r){
    tr[rt].l=l;tr[rt].r=r;
    if(l==r){
        tr[rt].maxx=dis[bf[l]];    
        return;
    }
    int mid=(l+r)>>1;
    build(rt<<1,l,mid);build(rt<<1|1,mid+1,r);
    pushup(rt);
}

void change(int rt,int l,int r,int qx,int qy,int z){
    if(qx<=l&&qy>=r){
        tr[rt].maxx+=z;
        tr[rt].s+=z;
        return;
    }
    int mid=(l+r)>>1;
    if(qy<=mid)change(rt<<1,l,mid,qx,qy,z);
    else if(qx>mid)change(rt<<1|1,mid+1,r,qx,qy,z);
    else {
        change(rt<<1,l,mid,qx,mid,z);
        change(rt<<1|1,mid+1,r,mid+1,qy,z);
    }
}

long long query(int rt,int l,int r,int qx,int qy){
    pushdown(rt);
    if(qx<=l&&qy>=r)return tr[rt].maxx;
    int mid=(l+r)>>1;
    if(qy<=mid)return query(rt<<1,l,mid,qx,qy);
    else if(qx>mid)return query(rt<<1|1,mid+1,r,qx,qy);
    else return max(query(rt<<1,l,mid,qx,mid),query(rt<<1|1,mid+1,r,mid+1,qy));
}

int main(){
    scanf("%d",&t);
    while(t--){
        memset(head,0,sizeof(head));
        sumedge=0;tim_node=0;cnt=0;
        scanf("%d%d",&n,&m);
        int x;long long y;
        for(int i=1;i<n;i++){
            scanf("%d%d",&x,&y);
            add(x,y);add(y,x);
        }
        for(int i=0;i<n;i++){
            cin>>dis[i];sum[i]=dis[i];
        }
        dfs(0,-1);
        build(1,0,n-1);
        for(int i=1;i<=m;i++){
            scanf("%d",&od);
            if(od==0){
                scanf("%d%lld",&x,&y);
                change(1,0,n-1,l[x],r[x],y-sum[x]);
                sum[x]=y;
            }else {
                scanf("%d",&x);
                ans[++cnt]=query(1,0,n-1,l[x],r[x]);
            }
        }
        if(cnt){
        printf("Case #%d:
",++kis);
        for(int i=1;i<=cnt;i++)printf("%lld
",ans[i]);
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/zzyh/p/7582751.html