【图论+线段树】[2016"百度之星" - 初赛(Astar Round2A)]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

#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序用线段树维护即可。

代码

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define MAXN 100000
int n,st[MAXN+10],ed[MAXN+10],dcnt,rdfn[MAXN+10],wt[MAXN+10],m,T;
long long dep[MAXN+10];
template<class T>
void Read(T &x){
    char c;
    bool f=0;
    while(c=getchar(),c!=EOF){
        if(c=='-')
            f=1;
        if(c>='0'&&c<='9'){
            x=c-'0';
            while(c=getchar(),c>='0'&&c<='9')
                x=x*10+c-'0';
            ungetc(c,stdin);
            if(f)
                x=-x;
            return;
        }
    }
}
struct node{
    int v;
    node *next;
}*adj[MAXN+10],edge[MAXN*2+10],*ecnt=edge;
inline void addedge(int u,int v){
    node *p=++ecnt;
    p->v=v;
    p->next=adj[u];
    adj[u]=p;
}
namespace SegmentTree{
struct node{
    long long mx,tag;
}tree[MAXN*4+10];
inline void update(int i){
    tree[i].mx=max(tree[i<<1].mx,tree[(i<<1)|1].mx);
}
inline void push_down(int i){
    if(tree[i].tag){
        tree[i<<1].mx+=tree[i].tag,tree[i<<1].tag+=tree[i].tag;
        tree[(i<<1)|1].mx+=tree[i].tag,tree[(i<<1)|1].tag+=tree[i].tag;
        tree[i].tag=0;
    }
}
void insert(int i,int l,int r,int ll,int rr,int d){
    if(ll<=l&&r<=rr){
        tree[i].tag+=d;
        tree[i].mx+=d;
        return;
    }
    if(ll>r||rr<l)
        return;
    push_down(i);
    int mid=(l+r)>>1;
    insert(i<<1,l,mid,ll,rr,d);
    insert((i<<1)|1,mid+1,r,ll,rr,d);
    update(i);
}
long long get_mx(int i,int l,int r,int ll,int rr){
    if(ll<=l&&r<=rr)
        return tree[i].mx;
    if(ll>r||rr<l)
        return 0x8000000000000000ll;
    push_down(i);
    int mid=(l+r)>>1;
    return max(get_mx(i<<1,l,mid,ll,rr),get_mx((i<<1)|1,mid+1,r,ll,rr));
}
void build(int i,int l,int r){
    tree[i].tag=0;
    if(l==r){
        tree[i].mx=dep[rdfn[l]];
        return;
    }
    int mid=(l+r)>>1;
    build(i<<1,l,mid);
    build((i<<1)|1,mid+1,r);
    update(i);
}
}
void dfs(int u,int fa){
    st[u]=++dcnt;
    dep[u]=dep[fa]+wt[u];
    rdfn[dcnt]=u;
    for(node *p=adj[u];p;p=p->next)
        if(p->v!=fa)
            dfs(p->v,u);
    ed[u]=dcnt;
}
using namespace SegmentTree;
void read(){
    Read(n),Read(m);
    int i,u,v;
    for(i=1;i<n;i++){
        Read(u),Read(v);
        addedge(u,v);
        addedge(v,u);
    }
    for(i=0;i<n;i++)
        Read(wt[i]);
}
void solve(){
    dep[0]=0;
    dfs(0,0);
    build(1,1,n);
    int p,x,y;
    while(m--){
        Read(p);
        if(!p){
            Read(x),Read(y);
            insert(1,1,n,st[x],ed[x],y-wt[x]);
            wt[x]=y;
        }
        else{
            Read(x);
            printf("%I64d\n",get_mx(1,1,n,st[x],ed[x]));
        }
    }
}
int main()
{
    Read(T);
    int cnt=0;
    while(T--){
        dcnt=0;
        printf("Case #%d:\n",++cnt);
        memset(adj,0,sizeof adj);
        ecnt=edge;
        read();
        solve();
    }
}
posted @ 2016-05-21 22:52  outer_form  阅读(225)  评论(0编辑  收藏  举报