树链剖分模板

模板题:洛谷2590

#include<cstdio>
#include<iostream>
using namespace std;
const int maxn = 30010;
inline int qread(){
    register int ch = getchar(), x = 0, flag = 0;
    while(ch < '0' || ch > '9')    {if(ch == '-')    flag = 1;    ch = getchar();}
    while(ch >= '0' && ch <= '9')    x = (x << 3) + (x << 1) + ch - 48, ch = getchar();
    return flag ? -x : x;
}
int head[maxn];
int go[maxn << 1];
int nxt[maxn << 1];

int n, q;
int val[maxn];

int son[maxn];
int deep[maxn];
int f[maxn];
int size[maxn];

int top[maxn];
int seg[maxn];
int rev[maxn];

int sum[maxn << 2];
int maxx[maxn << 2];
void dfs1(int x){
    size[x] = 1;
    for(register int i = head[x]; i; i =nxt[i]){
        if(!deep[go[i]]){
            f[go[i]] = x;
            deep[go[i]] = deep[x] + 1;
            dfs1(go[i]);
            size[x] += size[go[i]];
            if(size[go[i]] > size[son[x]])
                son[x] = go[i];
        }
    }
}
void dfs2(int x){
    if(son[x]){
        top[son[x]] = top[x];
        seg[son[x]] = ++seg[0];
        rev[seg[0]] = son[x];
        dfs2(son[x]);
    }
    for(register int i = head[x]; i; i = nxt[i]){
        if(!top[go[i]]){
            top[go[i]] = go[i];
            seg[go[i]] = ++seg[0];
            rev[seg[0]] = go[i];
            dfs2(go[i]);
        }
    }
}
inline void update(int x){
    sum[x] = sum[x << 1] + sum[x << 1 | 1];
    maxx[x] = max(maxx[x << 1], maxx[x << 1 | 1]);
}
void build(int x, int l, int r){
    if(l == r){
        sum[x] = maxx[x] = val[rev[l]];
        return;
    }
    int mid = (l + r) >> 1;
    build(x << 1, l, mid);
    build(x << 1 | 1, mid + 1, r);
    update(x);
}
int SUM, MAX;
void change(int l, int r, int P, int v, int x){
    if(l == r){
        maxx[x] = sum[x] = v;
        return ;
    }
    int mid = (l + r) >> 1;
    if(P <= mid)    change(l, mid, P, v, x << 1);
    else            change(mid + 1, r, P, v, x << 1 | 1);
    update(x);
}
void ask(int l, int r, int L, int R, int x){
    if(L <= l && R >= r){
        SUM += sum[x];
        MAX = max(MAX, maxx[x]);
        return ;
    }
    int mid = (l + r) >> 1;
    if(mid >= L)    ask(l, mid, L, R, x << 1);
    if(mid < R)        ask(mid + 1, r, L, R, x << 1 | 1);
}
void asktree(int x, int y){
    int fx = top[x], fy = top[y];
    while(fx != fy){
        if(deep[fx] < deep[fy])    swap(x, y), swap(fx, fy);
        ask(1, n, seg[fx], seg[x], 1);
        x = f[fx];
        fx = top[x];
    }
    if(deep[x] > deep[y])    swap(x, y);
    ask(1, n, seg[x], seg[y], 1);
}
void init(){
    n = qread();
    for(int i = 1; i < n; ++i){
        int x = qread(), y = qread();
        go[i] = y;    nxt[i] = head[x];    head[x] = i;
        go[i + n] = x;    nxt[i + n] = head[y];    head[y] = n + i;
    }
    for(int i = 1; i <= n; ++i)
        val[i] = qread();
    q = qread();
    rev[1] = top[1] = seg[0] = seg[1] = deep[1] = 1;
    dfs1(1);
    dfs2(1);
    build(1, 1, n);
}
int main(void){
    init();
    while(q--){
        string op;
        cin >> op;
        if(op == "QMAX"){
            int x = qread(), y = qread();
            MAX = 0x80000000;
            asktree(x, y);
            printf("%d\n", MAX);
        }
        else if(op == "QSUM"){
            int x = qread(), y = qread();
            SUM = 0;
            asktree(x, y);
            printf("%d\n", SUM);
        }
        else{
            int x = qread(), v = qread();
            change(1, n, seg[x], v, 1);    
        }
    }
}

 

posted @ 2018-08-23 17:08  junk_yao  阅读(104)  评论(0编辑  收藏  举报