1. 程式人生 > >HDU 5692 Snacks (DFS序 + 線段樹區間更新 好題)

HDU 5692 Snacks (DFS序 + 線段樹區間更新 好題)

 
題目連結:http://acm.hdu.edu.cn/showproblem.php?pid=5692

題目分析:其實就是求一棵子樹x裡到0點路徑權值和最大的點的那個權值和,因為是對一棵子樹的所有值,所以容易想到用DFS序來處理,改變x點權值則其子樹所有點到0點的路徑權值和都要更新,這樣就變成區間更新求最值問題,線段樹搞一下就可以了,本題巧妙的將DFS序和線段樹結合在一起

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <cstdio>
#include <cstring>
#include <algorithm>
#define ll long long
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
using namespace std;
ll const INF = 1e18;
int const MAX = 100005;
int n, m;
ll a[MAX], sum[MAX << 2], lazy[MAX << 2], dis[MAX];
int l[MAX], r[MAX], nd[MAX], num;
int head[MAX], cnt;

struct EDGE
{
    int to, nxt, val;
}e[MAX << 1];

void Init()
{
    num = 0;
    cnt = 0;
    memset(head, -1, sizeof(head));
}

void Add(int u, int v)
{
    e[cnt].to = v;
    e[cnt].nxt = head[u];
    head[u] = cnt ++;
}

void DFS(int u, int fa)
{
    num ++;
    l[u] = num;
    nd[num] = u;
    for(int i = head[u]; i != -1; i = e[i].nxt)
    {
        int v = e[i].to;
        if(v != fa)
        {
            dis[v] = dis[u] + a[v];
            DFS(v, u);
        }
    }
    r[u] = num;
}

void PushUp(int rt)
{
    sum[rt] = max(sum[rt << 1], sum[rt << 1 | 1]);
    return;
}

void PushDown(int rt)
{
    if(lazy[rt])
    {
        sum[rt << 1] += lazy[rt];
        sum[rt << 1 | 1] += lazy[rt];
        lazy[rt << 1] += lazy[rt];
        lazy[rt << 1 | 1] += lazy[rt];
        lazy[rt] = 0;
    }
    return;
}

void Build(int l, int r, int rt)
{
    lazy[rt] = 0;
    if(l == r)
    {
        sum[rt] = dis[nd[l]];
        return;
    }
    int mid = (l + r) >> 1;
    Build(lson);
    Build(rson);
    PushUp(rt);
}

void Update(int L, int R, int val, int l, int r, int rt)
{
    if(L <= l && r <= R)
    {
        lazy[rt] += val;
        sum[rt] += val;
        return;
    }
    int mid = (l + r) >> 1;
    PushDown(rt);
    if(L <= mid)
        Update(L, R, val, lson);
    if(mid < R)
        Update(L, R, val, rson);
    PushUp(rt);
}

ll Query(int L, int R, int l ,int r, int rt)
{
    if(L <= l && r <= R)
        return sum[rt];
    int mid = (l + r) >> 1;
    PushDown(rt);
    ll ans = -INF;
    if(L <= mid)
        ans = max(ans, Query(L, R, lson));
    if(mid < R)
        ans = max(ans, Query(L, R, rson));
    return ans;
}

int main()
{
    int T;
    scanf("%d", &T);
    for(int ca = 1; ca <= T; ca++)
    {
        printf("Case #%d:\n", ca);
        Init();
        int x, y;
        scanf("%d %d", &n, &m);
        for(int i = 0; i < n - 1; i++)
        {
            scanf("%d %d", &x, &y);
            Add(x, y);
            Add(y, x);
        }
        for(int i = 0; i < n; i++)
            scanf("%I64d", &a[i]);
        dis[0] = a[0];
        DFS(0, -1);
        Build(1, n, 1);
        while(m --)
        {
            int tp, x, y;
            scanf("%d", &tp);
            if(tp == 1)
            {
                scanf("%d", &x);
                printf("%I64d\n", Query(l[x], r[x], 1, n, 1));
            }
            else
            {
                scanf("%d %d", &x, &y);
                Update(l[x], r[x], y - a[x], 1, n, 1);
                a[x] = y;
            }
        }
    }
}


相關推薦

HDU 5692 Snacks (DFS + 線段區間更新 )

  題目連結:http://acm.hdu.edu.cn/showproblem.php?pid=5692 題目分析:其實就是求一棵子樹x裡到0點路徑權值和最大的點的那個權值和,因為是對一棵子樹的所有值,所以容易想到用DFS序來處理,改變x點權值則其子樹所有點到0點的路徑權值和都要更新,這樣就變成區間更新求最

5692 Snacks DFS+線段

思路 求子樹x中到根節點的最大值。修改時需要將子樹x的所有點都修改。則本題變成一個區間更新,區間最值的題。dfs序處理後,套一個支援區間更新的線段樹即可。  每個葉子節點儲存的都是0到他所對應的標號(第幾臺零食機)的距離,每一次pushup時都會找出對應區間的最大值 #

zoj 3686 - A Simple Tree Problem (dfs+線段區間更新

Given a rooted tree, each node has a boolean (0 or 1) labeled on it. Initially, all the labels are 0. We define this kind of operation: given a

3974 DFS+線段區間更新/查詢

題意 一個公司有n個人,有一個人是領導(等級最高)沒有上司,其餘每個人都有一個上司。 給定m個要求,當輸入為“C x”時,輸出x當前的任務;當輸入為"T x y"時,給x分配一個任務y(此時,x和x的下屬都需要放棄原來的任務,執行當前的任務y)。 思路 dfs序+

hdu5692 Snacks dfs+線段

mathjax \n class == -- c++ tin blank color 題目傳送門 題目大意:給出一顆樹,根節點是0,有兩種操作,一是修改某個節點的value,二是查詢,從根節點出發,經過 x 節點的路徑的最大值。 思路:用樹狀數組寫發現還是有些麻煩,最後用線

HDU 1698 Just a Hook 線段 區間更新

不同 描述 感覺 ring 這也 deque deb %d total   題目鏈接: http://acm.hdu.edu.cn/showproblem.php?pid=1698   題目描述: 區間更新, 最後求出1 ~ n 之和     解題思路: 這裏涉及到區間

HDU 1698 Just a Hook (線段區間更新入門

follow and iostream http span meta ali pos num Just a Hook Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/O

HDU——3577 Fast Arrangement (線段+區間更新+最值查詢)

Chinese always have the railway tickets problem because of its' huge amount of passangers and stations. Now goverment need you to develop a new ticket

hdu 6273 Master of GCD (線段+區間更新)

Problem J. Master of GCD Hakase has n numbers in a line. At first, they are all equal to 1. Besides, Hakase is interested in primes. She will choose a

HDU-1698 Just a Hook 線段區間更新

題意:一個長度為n的線段,q個操作,每個操作x,y,z是指把區間[x,y]內的值修改為z,最後求線段值的和。 思路:增加懶惰標誌,每次更新操作只更新到這個區間節點而不是這個區間的所有葉子結點。例如操作1,5,2。只更新到節點[1,5]而不是他的五個葉子結點

HDU 1698 Just a Hook (線段區間更新

Problem Description In the game of DotA, Pudge’s meat hook is actually the most horrible thing for most of the heroes. The hook is made

hdu 3016 Man Down(線段區間更新+dp)

題意: 是男人就下100層相信很多人都玩過,這題就是簡單的模擬這個遊戲。 有n塊木板,每塊木板有4個屬性,高h(h>0),左邊界,右邊界,以及掉落在它上面,獲得多少生命值,一個人從最

HDU 1156 Color the ball (線段 區間更新)

Color the ball                                                                       Time Limit: 9000/3000 MS (Java/Others)    Memory Li

hdu 4893 Wow! Such Sequence! (線段 區間更新+單點更新)

/* 1 k d 第k個數加d 2 l r 查詢l到r的和 3 l r l到r更新到最近的f[] */ # include <stdio.h> # include <algorithm> # include <string.h> usin

Codeforces 46 D Parking Lot(線段區間更新模板

題目地址 題意:有長度為n米的停車場,停車的要求是要與前面一輛車至少隔a米,和後一輛車至少隔b米(只要符合要求就可以停入,不管之後會不會打破這個要求。PS:我就是想了好久沒有想通),有m個操作,有兩種操作型別: 1 x 把長度為x米的車停入停車場(一定要符

HDU-5692-SnacksDFS+線段,單點修改,區間查詢)

題目連結:http://acm.hdu.edu.cn/showproblem.php?pid=5692 Problem Description 百度科技園內有n 個零食機,零食機之間通過n−1 條路相互連通。每個零食機都有一個值v ,表示為小度熊提供零食的價值。 由於零

hdu 5692 Snacks】【dfs】【線段】【

【連結】 http://acm.hdu.edu.cn/showproblem.php?pid=5692 【題意】 樹上兩種操作: 0 x y 將x的權重變為y 1 x 求出從0出發,經過x的路徑的最距離和 【分析】 其實就是求一棵子樹x裡到0點路徑權值和最大的點的那個權值

hdu 5692 (dfs+線段

wange2014   |   We have carefully selected several similar problems for you:  5932 5931 5930 5929 5928  題解:萬萬沒想到會爆int,導致查了好久的錯, 先用dfs處理出一個從0到每個點的距離,那麼經過一個點

HDU 3974 Assign the task(DFS+線段

string ssi 組成 ase target 區間 兩張 img lan 題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=3974 題意:n名員工組成一棵樹,分配任務給其中一名員工,那麽他和他的手下(就是該節點的全部子節點

HDU5692 Snacksdfs + 線段

#pragma comment(linker, "/STACK:1024000000,1024000000") #include <iostream> #include <vector> #include <algorithm> #include <utility&