zoukankan      html  css  js  c++  java
  • hdu5692 Snacks dfs序+线段树

    题目传送门

    题目大意:给出一颗树,根节点是0,有两种操作,一是修改某个节点的value,二是查询,从根节点出发,经过 x 节点的路径的最大值。

    思路:用树状数组写发现还是有些麻烦,最后用线段树了。

       其实这道题的查询,就是查询从根节点到x节点+x节点走下去的路径的最大值,这样会发现,其实就是查询包括x节点的所有子树中权值最大的那个,而包括x节点的子树,如果用dfs序转换一下的话,可以在线段上用一段连续的点表示出来,所以最后就转换成了线段树区间求最大值,然后单点修改的题目了。

      要注意的是dfs序和原标号的对应,有一个地方弄反了,卡了好久。

    #pragma comment(linker, "/STACK:1024000000,1024000000") 
    #include<cstdio>
    #include<cstring>
    #include<stdlib.h>
    #include<algorithm>
    #include<iostream>
    #include<cmath>
    #include<map>
    #define CLR(a,b) memset(a,b,sizeof(a))
    #define PI acos(-1)
    #define lson rt*2,l,(l+r)/2
    #define rson rt*2+1,(l+r)/2+1,r
    using namespace std;
    typedef long long ll;
    const int inf=0x3f3f3f3f;
    const int maxn=100010;
    struct edge{
        int to,Next;
    }e[maxn*2];
    int tot,m,n,head[maxn],pos,dfn[maxn],fa[maxn],son[maxn],l[maxn],r[maxn];
    ll val[maxn],dis[maxn];
    inline void init(){
        CLR(head,-1),tot=0,pos=0;
        CLR(dis,0);
        fa[1]=1;
    }
    inline void addv(int u,int v){
        e[++tot]={v,head[u]};
        head[u]=tot;
    }
    ll tree[maxn << 2], laz[maxn << 2];
    inline void pushup(int rt) {
        tree[rt] = max(tree[rt << 1], tree[rt << 1 | 1]);
    }
    inline void pushdown(int rt) {
        if (laz[rt]) {
            tree[rt << 1] += laz[rt];
            tree[rt << 1 | 1] += laz[rt];
            laz[rt << 1] += laz[rt];
            laz[rt << 1 | 1] += laz[rt];
            laz[rt] = 0;
        }
    }
    inline void build(int rt, int l, int r) {
        laz[rt] = 0;
        if (l == r) {
            tree[rt] = dis[l];
            return ;
        }
        build(lson);
        build(rson);
        pushup(rt);
    }
    inline void update(int L, int R, ll v, int rt, int l, int r) {
        if (L <= l && R >= r) {
            tree[rt] += v;
            laz[rt] += v;
            return;
        }
        pushdown(rt);
        if (L <= (l + r) / 2)   update(L, R, v, lson);
        if (R > (l + r) / 2)    update(L, R, v, rson);
        pushup(rt);
    }
    inline ll query(int L, int R, int rt, int l, int r) { 
        if (L <= l && R >= r) {
            return tree[rt];
        }
        pushdown(rt);
        if (L > (l + r) / 2)    return query(L,R,rson);
        else if (R <= (l + r) / 2)  return query(L,R,lson);
        else return max(query(L,R,lson),query(L,R,rson));
    }
    
    inline void dfs(int u,int pre){
        dfn[u]=++pos;
        l[u]=pos;
        son[u]=1;
        dis[dfn[u]]=dis[dfn[pre]]+val[u];
        for(int i=head[u];i!=-1;i=e[i].Next)
        {
            int v=e[i].to;
            if(v==fa[u])continue;
            fa[v]=u;
            
            dfs(v,u);
            son[u]+=son[v];
        }
        r[u]=pos;
    }
    int main(){
        int T,cas=1;
        cin>>T;
        while(T--){
            init();
            scanf("%d%d",&n,&m);
            
            for(int i=1;i<n;i++){
                int u,v;
                scanf("%d%d",&u,&v);
                addv(u+1,v+1);
                addv(v+1,u+1);
            }
            
            for(int i=1;i<=n;i++)scanf("%lld",&val[i]);
            dfs(1,1);
            build(1,1,n);
            printf("Case #%d:
    ",cas++);
            while(m--){
                int op,x;ll y;
                scanf("%d%d",&op,&x);
                if(op==1){
                //    printf("debug  %d  %d
    ",dfn[x+1],dfn[x+1]+son[x+1]-1);
                
                    printf("%lld
    ",query(l[x+1],r[x+1],1,1,n));
                }else{
                    scanf("%lld",&y);
                    update(l[x+1],r[x+1],y-val[x+1],1,1,n);
                    val[x+1]=y;
                }
            }
            
        }
    }

    Snacks

    Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
    Total Submission(s): 5563    Accepted Submission(s): 1265


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

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

    为小度熊规划一个路线,使得路线上的价值总和最大。
     
    Input
    输入数据第一行是一个整数T(T10),表示有T组测试数据。

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

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

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

    接下来m行,有两种操作:0 x y,表示编号为x的零食机的价值变为y1 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
  • 相关阅读:
    在Android中如何获取视频的第一帧图片并显示在一个ImageView中
    利用MsChart控件绘制多曲线图表 z
    国外成熟的程序交易系统的思路 z
    稳健获利
    用vmware安装gho文件
    数学之美 zt
    大型邮箱smtp服务器及端口 收集
    英语之路 zt
    C# Get Desktop Screenshot ZZ
    C#/PHP Compatible Encryption (AES256) ZZ
  • 原文地址:https://www.cnblogs.com/mountaink/p/9863097.html
Copyright © 2011-2022 走看看