loj10138. 「一本通 4.5 例 1」树的统计

思路:
  树链剖分模板题

#include<cstdio>
#include<iostream>
#include<vector>
#include<cmath>
#include<string>
using namespace std;
const int maxn = 30010;
inline void qread(int &x){
    x = 0;
    register int ch = getchar(), flag = 0;
    while(ch < '0' || ch > '9')    {
        if(ch == '-')    flag = 1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
        x = 10 * x + ch - 48, ch = getchar();
    if(flag)    x = -x;    
}
int n, m, rt = 1;
int val[maxn];
int head[maxn];
int go[maxn << 1];
int nxt[maxn << 1];

int f[maxn];
int deep[maxn];
int size[maxn];
int son[maxn];
int top[maxn];
int seg[maxn];
int rev[maxn];

int maxx[maxn << 2];
int sum[maxn << 2];
int MAX, SUM;
inline void init(){
    qread(n);    
    for(register int i=1; i<n; ++i){
        register int x, y;
        qread(x), qread(y);
        go[i] = y;
        go[i + n] = x;
        nxt[i] = head[x];
        head[x] = i;
        nxt[i + n] = head[y];
        head[y] = i + n;
    }
    for(int i=1; i<=n; ++i)
        qread(val[i]);
    qread(m);
    deep[rt] = 1;
    seg[0] = seg[1] = rev[1] = top[1] = 1;
}
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]){
        seg[son[x]] = ++seg[0];
        top[son[x]] = top[x];
        rev[seg[0]] = son[x];
        dfs2(son[x]);
    }
    for(register int i = head[x]; i; i = nxt[i]){
        if(!top[go[i]]){
            seg[go[i]] = ++seg[0];
            rev[seg[0]] = go[i];
            top[go[i]] = go[i];
            dfs2(go[i]);
        }
    }
}
void segbuild(int l, int r, int x){
    if(l==r){
        sum[x] = maxx[x] = val[rev[l]];
        return ;
    }
    int mid = (l + r) >> 1;
    segbuild(l, mid, x << 1);
    segbuild(mid + 1, r, x << 1 | 1);
    sum[x] = sum[x << 1] + sum[x << 1 | 1];
    maxx[x] = max(maxx[x << 1], maxx[x << 1 | 1]);
} 
void segchange(int l, int r, int P, int v, int x){
    if(l == r){
        sum[x] = maxx[x] = v;
        return ;
    }
    int mid = (l + r) >> 1;
    if(mid >= P)    segchange(l, mid, P, v, x << 1);
    else            segchange(mid + 1, r, P, v, x << 1 | 1);
    sum[x] = sum[x << 1] + sum[x << 1 | 1];
    maxx[x] = max(maxx[x << 1], maxx[x << 1 | 1]);
}
void segquery(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)    segquery(l, mid, L, R, x << 1);
    if(mid < R)        segquery(mid + 1, r, L, R,  x << 1 | 1);
}
void treeask(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);
        segquery(1, seg[0], seg[fx], seg[x], 1);
        x = f[fx];
        fx = top[x];
    }
    if(deep[x] > deep[y])    swap(x, y);
    segquery(1, seg[0], seg[x], seg[y], 1); 
}
int main(void){
    init();
    dfs1(rt);
    dfs2(rt);
    segbuild(1, seg[0], 1);
    while(m--){
         string op;
         cin >> op;
         SUM = 0, MAX = 0x80000000;
         if(op == "CHANGE"){
             int x, y;
             qread(x), qread(y);
             segchange(1, seg[0], seg[x], y, 1);
         }
         else {
            int x, y;
             qread(x), qread(y);
             treeask(x, y);
            if(op == "QMAX")
                 printf("%d\n", MAX);
             else
                 printf("%d\n", SUM);
        }
    }
}

猜你喜欢

转载自www.cnblogs.com/junk-yao-blog/p/9480442.html