码迷,mamicode.com
首页 > 其他好文 > 详细

GG--树链剖分

时间:2017-11-25 20:50:00      阅读:170      评论:0      收藏:0      [点我收藏+]

标签:etc   namespace   nbsp   std   max   pre   dfs   getc   continue   

怎么也调不出来

#include <bits/stdc++.h>

using namespace std;
const int N = 3e4 + 10; 

#define gc getchar()
#define lson jd << 1
#define rson jd << 1 | 1 
#define INF 1000000000
#define LL long long

int n, m, now = 1, Tree_clock;
LL ans_max, ans_sum;
int head[N];
int tree[N], bef[N], deep[N], f[N], son[N], size[N], topp[N], data[N];
struct Node{
    int v, nxt;
}G[N * 2];
struct node{
    int l, r;
    LL w, max;
}T[N << 2];

inline int read(){
    int x = 0, f = 1; char c = gc;
    while(c < 0 || c > 9){if(c == -) f = -1; c = gc;} 
    while(c >= 0 && c <= 9) x = x * 10 + c - 0, c = gc;
    return x * f;
}

inline void add(int u, int v){
    G[now].v = v;
    G[now].nxt = head[u];
    head[u] = now ++;
}

void dfs_find_son(int u, int fa, int dep){
    f[u] = fa;
    deep[u] = dep;
    size[u] = 1;
    for(int i = head[u]; ~ i; i = G[i].nxt){
        int v = G[i].v;
        if(v == fa) continue ;
        dfs_find_son(v, u, dep + 1);
        size[u] += size[v];
        if(!son[u] || size[son[u]] < size[v]) son[u] = v;
    } 
}

void dfs_un_son(int u, int tp){
    topp[u] = tp;
    tree[u] = ++ Tree_clock;
    bef[tree[u]] = u;
    if(!son[u]) return ;
    dfs_un_son(son[u], tp);
    for(int i = head[u]; ~ i; i = G[i].nxt){
        int v = G[i].v;
        if(v != f[u] && v != son[u]) dfs_un_son(v, v);
    }
}

void build_tree(int l, int r, int jd){
    T[jd].l = l;
    T[jd].r = r;
    if(l == r){
        T[jd].w = T[jd].max = data[bef[l]];
        return ;
    }
    int mid = (l + r) >> 1;
    build_tree(l, mid, lson);
    build_tree(mid + 1, r, rson);
    T[jd].max = max(T[lson].max, T[rson].max);
    T[jd].w = T[lson].w + T[rson].w;
}

void Sec_G(int l, int r, int jd, int x, int yj){
    if(l == r){
        T[jd].w += yj;
        T[jd].max += yj;
        return ;
    }
    int mid = (l + r) >> 1;
    if(x <= mid) Sec_G(l, mid, lson, x, yj);
    else Sec_G(mid + 1, r, rson, x, yj);
    T[jd].max = max(T[lson].max, T[rson].max);
     T[jd].w = T[lson].w + T[rson].w;
  }

void ask_max(int l, int r, int jd, int x, int y){
    if(x <= l && r <= y){
        ans_max = max(ans_max, T[jd].max);
        return ;
    }
    int mid = (l + r) >> 1;
    if(x <= mid) ask_max(l, mid, lson, x, y);
    if(y > mid) ask_max(mid + 1, r, rson, x, y);
}

void ask_sum(int l, int r, int jd, int x, int y){
    if(x <= l && r <= y){
        ans_sum += T[jd].w;
        return ;
    }
    int mid = (l + r) >> 1;
    if(x <= l) ask_sum(l, mid, lson, x, y);
    if(y > mid) ask_sum(mid + 1, r, rson, x, y);
}

int find_max(int x, int y){
    int tp1 = topp[x], tp2 = topp[y];
    LL ans = - INF;
    while(tp1 != tp2){
        if(deep[tp1] < deep[tp2]) swap(x, y), swap(tp1, tp2);
        ans_max = -INF;
        ask_max(1, n, 1, tree[tp1], tree[x]);
        ans = max(ans, ans_max);
        x = f[tp1];
        tp1 = topp[x];
    }
    ans_max = - INF;
    if(deep[x] > deep[y]){
        ask_max(1, n, 1, tree[y], tree[x]);
        ans = max(ans, ans_max);
    } 
    else{
        ask_max(1, n, 1, tree[x], tree[y]);
        ans = max(ans, ans_max);
    } 
    return ans;
}

int find_sum(int x, int y){
    int tp1 = topp[x], tp2 = topp[y]; 
    LL ans = 0;
    while(tp1 != tp2){
        if(deep[tp1] < deep[tp2]) swap(x, y), swap(tp1, tp2);
        ans_sum = 0;
        ask_sum(1, n, 1, tree[tp1], tree[x]);
        ans += ans_sum;
        x = f[x];
        tp1 = topp[x];
    }
    ans_sum = 0;
    if(deep[x] > deep[y]){
        ask_sum(1, n, 1, tree[y], tree[x]);
        ans += ans_sum;
    }
    else {
        ask_sum(1, n, 1, tree[x], tree[y]);
        ans += ans_sum;
    }
    return ans;
}

int main()
{
    freopen("bzoj_1036.in", "r", stdin);
    freopen("bzoj_1036.out", "w", stdout);
    n = read();
    for(int i = 1; i <= n; i ++) head[i] = -1;
    for(int i = 1; i < n; i ++){
        int u = read();
        int v = read();
        add(u, v);
        add(v, u);
    }
    for(int i = 1; i <= n; i ++) data[i] = read();
    dfs_find_son(1, 0, 1);//当前节点, 父亲, 深度 
    dfs_un_son(1, 1);
    build_tree(1, n, 1);
    m = read();
    while(m --){
        string how; int x, y; cin >> how; x = read(); y = read();
        if(how[0] == C){//修改
            Sec_G(1, n, 1, tree[x], y - data[x]);
            data[x] = y;
        }
        else if(how[1] == M) cout << find_max(x, y) << endl;
        else cout << find_sum(x, y) << endl;
    }
    return 0;
}
/*
5
1 2
1 3
3 4
3 5
1 2 3 4 5
12
QMAX 3 4
QMAX 3 3
QMAX 3 2
QMAX 2 3
QSUM 3 4
QSUM 2 1
CHANGE 1 5
QMAX 3 4
CHANGE 3 6
QMAX 3 4
QMAX 2 4
QSUM 3 4
*/

 

GG--树链剖分

标签:etc   namespace   nbsp   std   max   pre   dfs   getc   continue   

原文地址:http://www.cnblogs.com/shandongs1/p/7896217.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!