• O


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

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

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

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

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

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

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

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

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

    `#pragma comment(linker, "/STACK:1024000000,1024000000") `
    Output对于每组数据,首先输出一行”Case #?:”,在问号处应填入当前数据的组数,组数从1开始计算。 

    对于每次询问,输出从编号为0的零食机出发,必须经过编号为xx零食机的路线中,价值总和的最大值。 
    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标记每个点的时间戳,并且记录到每个点的路径(同时开一个Rev数组,从时间戳返回到原节点,建线段树的时候要用到).
    知道了每个节点的时间戳,就知道了该节点的子树的区间,为[Start[x],End[x]],更新的话用线段树区间更新,查询的话用线段树区间查询,用到lazy数组.
    #pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn=100010;
    const ll INF=0x3f3f3f3f3f3f3f3f;//这里一定是long long 啊啊啊啊
    ll head[maxn],dis[maxn],w[maxn],Rev[maxn];
    int Start[maxn],End[maxn];
    int tot,cnt,n,m;
    ll sum[maxn<<2],lazy[maxn<<2];
    struct node
    {
        ll v,next;
    }e[maxn<<1];
    void add(int u,int v)
    {
        e[tot]=(node){v,head[u]};
        head[u]=tot++;
    }
    void DFS(int u,int pre)
    {
        Start[u]=++cnt;
        Rev[cnt]=u;
        for(int i=head[u];i!=-1;i=e[i].next){
            int v=e[i].v;
            if(v==pre)continue;
            dis[v]=dis[u]+w[v];
            DFS(v,u);
        }
        End[u]=cnt;
    }
    void pushup(int rt)
    {
        sum[rt]=max(sum[rt*2],sum[rt*2+1]);
    }
    void pushdown(int rt)
    {
        if(lazy[rt]){
            lazy[rt<<1]+=lazy[rt];
            lazy[rt<<1|1]+=lazy[rt];
            sum[rt<<1]+=lazy[rt];
            sum[rt<<1|1]+=lazy[rt];
            lazy[rt]=0;
        }
    }
    void build(int l,int r,int rt)
    {
        lazy[rt]=0;
        if(l==r){
            sum[rt]=dis[Rev[l]];
            return ;
        }
        int mid=(l+r)/2;
        build(l,mid,rt*2);
        build(mid+1,r,rt*2+1);
        pushup(rt);
    }
    void update(int L,int R,int w,int l,int r,int rt)//[L,R]区间加上w
    {
        if(L<=l&&R>=r){
            sum[rt]+=w;
            lazy[rt]+=w;
            return ;
        }
        pushdown(rt);
        int mid=(l+r)>>1;
        if(L<=mid)update(L,R,w,l,mid,rt<<1);
        if(R>=mid+1)update(L,R,w,mid+1,r,rt<<1|1);
        pushup(rt);
    }
    ll querymax(int L,int R,int l,int r,int rt)
    {
        if(L<=l&&R>=r){
            return sum[rt];
        }
        pushdown(rt);
        ll ans=-INF;
        int mid=(l+r)>>1;
        if(L<=mid)ans=max(ans,querymax(L,R,l,mid,rt<<1));
        if(R>=mid+1)ans=max(ans,querymax(L,R,mid+1,r,rt<<1|1));
        return ans;
    }
    int main()
    {
        int T,k=1;
        scanf("%d",&T);
        while(T--){
            cnt=tot=0;
            scanf("%d%d",&n,&m);
            memset(head,-1,sizeof(head));
    
            for(int i=1;i<=n-1;i++){
                int u,v;
                scanf("%d%d",&u,&v);
                u++;
                v++;
                add(u,v);
                add(v,u);
            }
            for(int i=1;i<=n;i++)scanf("%lld",&w[i]);
            dis[1]=w[1];
            DFS(1,-1);
            build(1,n,1);
            printf("Case #%d:
    ", k++);
            while(m--){
                int op,x,y;
                scanf("%d%d",&op,&x);
                x++;
                if(op==1){
                    printf("%lld
    ",querymax(Start[x],End[x],1,n,1));
                }
                else{
                    scanf("%d",&y);
                    update(Start[x],End[x],y-w[x],1,n,1);
                    w[x]=y;
                }
            }
        }
        return 0;
    }
  • 相关阅读:
    Linux帮助都有哪几种,如何使用?
    描述linux目录结构以及目录结构命名规定
    常见Linux的发行版有哪些?并描述不同发行版之间的联系与区别。
    【redis常用的键值操作及性能优化】
    【防护墙学习-1】
    【生成树中易混淆的概念及拓扑集】
    【linux运维递进】
    【windows中常用的服务概览和总结】
    【shell脚本学习-4】
    【shell脚本学习-3】
  • 原文地址:https://www.cnblogs.com/cherish-lin/p/11274509.html
Copyright © 2020-2023  润新知