HDU5692(dfs + 線段樹)

題解:是個好題,對於經過某一點的最大值,可以將某一點作爲根,他的子樹中到0的最大值即爲解。那麼這樣,可以用dfs跑出一個序,即當前點到0的值,每個點維護一個L,R區間,那麼這個區間的點就是它的子樹。對於單點更新一個值,那麼就變成區間更新,更新這個點L,R區間所以點的值,對於查詢,就是L,R區間中的最大值
(注意LL和INF)

#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
#include <cstdio>
#include <string>
#include <cstring>
#include <vector>
#include <set>
#include <cmath>
#define LL long long
#define INF 1e18
#define mod 1000000007
const int maxn = 100000 + 5;
using namespace std;
int n,m,cnt,idx;
LL a[maxn];
int head[maxn];
int L[maxn];
int R[maxn];
LL dis[maxn];
LL lazy[maxn*4];
LL ans[maxn*4];
int ver[maxn];//dfs序數組的下標
struct Edge{
    int to;
    int next;
}edge[maxn*2];
void init(){
    cnt = idx = 0;
    memset(head, -1, sizeof(head));
    memset(lazy, 0, sizeof(lazy));
}
void addedge(int u, int v){
    edge[cnt].to = v;
    edge[cnt].next = head[u];
    head[u] = cnt++;
}
void dfs(int cur, int fa){
    L[cur] = ++idx;
    ver[idx] = cur;
    for(int i=head[cur]; i!=-1; i=edge[i].next){
        int v = edge[i].to;
        if(v != fa) {
            dis[v] = dis[cur] + a[v];
            dfs(v,cur);
        }
    }
    R[cur] = idx;

}
void pushdown(int o){
    if(lazy[o]){
        ans[o*2] += lazy[o];
        ans[o*2+1] += lazy[o];
        lazy[o*2] += lazy[o];
        lazy[o*2+1] += lazy[o];
        lazy[o] = 0;
    }
    return;
}
void build(int l, int r, int o){
    if(l == r){
        ans[o] = dis[ver[l]];
        return;
    }
    int m = (l+r)/2;
    build(l,m,o*2);
    build(m+1,r,o*2+1);
    ans[o] = max(ans[o*2],ans[o*2+1]);
    return;
}

void update(int val, int ql, int qr, int l, int r, int o){
    if(ql <= l && qr >= r){
        lazy[o] += val;
        ans[o] += val;
        return;
    }
    int m = (l+r)/2;
    pushdown(o);
    if(m >= ql)
        update(val,ql,qr,l,m,o*2);
    if(m < qr)
        update(val,ql,qr,m+1,r,o*2+1);
    ans[o] = max(ans[o*2],ans[o*2+1]);
}
LL query(int ql, int qr, int l, int r, int o){
    if(ql <= l && qr >= r)
        return ans[o];
    int m = (l+r)/2;
    pushdown(o);
    LL ANS = -INF;
    if(m >= ql)
        ANS = max(ANS, query(ql,qr,l,m,o*2));
    if(m < qr)
        ANS = max(ANS, query(ql,qr,m+1,r,o*2+1));
    return ANS;
}
int main(){
    int T, kases = 1;
    scanf("%d",&T);
    while(T--){
        init();
        scanf("%d%d",&n,&m);
        for(int i=0; i<n-1; i++){
            int u,v;
            scanf("%d%d",&u,&v);
            addedge(u, v);
            addedge(v, u);
        }
        for(int i=0; i<n; i++)
            scanf("%lld",&a[i]);
        dis[0] = a[0];
        dfs(0,-1);//跑出一個dfs序數組
//        for(int i=1; i<=n; i++)
//            cout << ver[i] << " ";
//        cout << endl;
//        for(int i=0; i<n; i++){
//            cout << "i : " << i << " L = " << L[i] << "  R = " << R[i] << endl;
//        }
        build(1,n,1);
        printf("Case #%d:\n",kases++);
        while(m--){
            int op,x,y;
            scanf("%d",&op);
            if(op == 1){
                scanf("%d",&x);
                printf("%lld\n",query(L[x],R[x],1,n,1));
            }
            else{
                scanf("%d%d",&x,&y);
                update(y-a[x],L[x],R[x],1,n,1);
                a[x] = y;
            }
        }
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章