zoukankan      html  css  js  c++  java
  • HDU5692 dfs + 线段树维护区间最大值

      先附上题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5692

      

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

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

    为小度熊规划一个路线,使得路线上的价值总和最大。
     
      分析:我们可以利用后序遍历将树上的每个节点编号, 这样的话一个顶点的叶子结点肯定在他的前面, 我们用l[x] r[x]表示x以及x的所有叶子结点,这样对于1 x的查询我们只需要找出l[x] r[x]区间的最大值即可, 对于0 x y我们只需要调整l[x] r[x]区间的值即可,  因为调整了一个顶点的点权之后只影响该点以及该点的叶子结点的权值。代码如下:
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <vector>
    #include <iostream>
    
    using namespace std;
    typedef long long LL;
    const int maxn = 100000 + 100;
    int n, m;
    vector<int> tree[maxn];
    int node_weight[maxn];
    LL num[maxn];
    int l[maxn], r[maxn], nlr;
    
    struct Segment {
        int l, r;
        LL x;
        LL lazy;
    }seg[3*maxn];
    
    void build(int rt, int l, int r) {
        seg[rt].l = l; seg[rt].r = r;
        if(l == r) {
            seg[rt].x = num[l];
            seg[rt].lazy = 0;
            return ;
        }
        build(2*rt, l, (l+r)/2);
        build(2*rt+1, (l+r)/2+1, r);
        seg[rt].x = max(seg[2*rt].x, seg[2*rt+1].x);
        seg[rt].lazy = 0;
    }
    
    void push_down(int rt) {
        if(seg[rt].lazy != 0){
            int chl = 2*rt;
            seg[chl].x += seg[rt].lazy;
            seg[chl].lazy += seg[rt].lazy;
            int chr = 2*rt + 1;
            seg[chr].x += seg[rt].lazy;
            seg[chr].lazy += seg[rt].lazy;
            seg[rt].lazy = 0;
        }
    }
    
    void push_up(int rt) {
        seg[rt].x = max(seg[2*rt].x, seg[2*rt+1].x);
    }
    
    LL query(int rt, int l, int r) {    //查询区间l - r的最大值
        if(seg[rt].l == l && seg[rt].r == r) {
            return seg[rt].x;
        }
        push_down(rt);
        int mid = (seg[rt].l + seg[rt].r)/2;
        if(r <= mid)
            return query(2*rt, l, r);
        else if(l > mid)
            return query(2*rt+1, l, r);
        else {
            LL v1 = query(2*rt, l, mid);
            LL v2 = query(2*rt+1, mid+1, r);
            return max(v1, v2);
        }
    }
    
    void update(int rt, int l, int r, int c) {     // 区间l-r增加C
        if(seg[rt].l == l && seg[rt].r == r) {
            seg[rt].x += c;
            seg[rt].lazy += c;
            return ;
        }
        push_down(rt);
        int mid = (seg[rt].l + seg[rt].r)/2;
        if(r <= mid)
            update(2*rt, l, r, c);
        else if(l > mid)
            update(2*rt+1, l, r, c);
        else {
            update(2*rt, l, mid, c);
            update(2*rt+1, mid+1, r, c);
        }
        push_up(rt);
    }
    
    
    void dfs(int pre, int u, int &k, LL sum) {
        l[u] = 2*maxn;
        int son = 0;
        sum += node_weight[u];
        for(int i=0; i<tree[u].size(); i++) {
            int v = tree[u][i];
            if(v == pre) continue;
            son++;
            dfs(u, v, k, sum);
            l[u] = min(l[u], l[v]);
        }
        num[k] = sum;
        r[u] = k++;
    //    printf("%d ", u);   ////////////////////////////
        if(son == 0) l[u] = r[u];
    }
    
    int main() {
        int T;
        scanf("%d", &T);
        int kase = 0;
        while(T--) {
            scanf("%d%d", &n, &m);
            for(int i=0; i<n; i++) tree[i].clear();
            for(int i=0; i<n-1; i++) {
                int u, v;
                scanf("%d%d", &u, &v);
                tree[u].push_back(v);
                tree[v].push_back(u);
            }
            for(int i=0; i<n; i++) scanf("%d", &node_weight[i]);
            nlr = 0;
            dfs(-1, 0, nlr, 0);
    //        printf("
    ");    //////////////////////////////////
    //        for(int i=0; i<n; i++)
    //            printf("l[%d] = %d, r[%d] = %d
    ", i, l[i], i, r[i]);
            build(1, 0, nlr-1);
            printf("Case #%d:
    ", ++kase);
            for(int i=0; i<m; i++) {
                int op;
                scanf("%d", &op);
                if(op == 0) {
                    int x, y;
                    scanf("%d%d", &x, &y);
                    update(1, l[x], r[x], y-node_weight[x]);
                    node_weight[x] = y;
                }else{
                    int x;
                    scanf("%d", &x);
                    LL res = query(1, l[x], r[x]);
                    cout<<res<<endl;
                }
            }
        }
        return 0;
    }
     
  • 相关阅读:
    清理一瓶花茶中的虫子
    一些网上的新信息安全问题
    对于秋季高程备课的随笔
    用共享单车第一次遇到程序出现问题的思考
    开始带学生的一些感受
    对近期北辰开会的一些总结
    WSN和RFID书上好多问题:关于S50
    统计课设成绩用到excel画成绩频率分布曲线
    linux 常用命令
    局域网 ARP 欺骗原理详解
  • 原文地址:https://www.cnblogs.com/xingxing1024/p/5550529.html
Copyright © 2011-2022 走看看