再次救助树链剖分
查看原帖
再次救助树链剖分
40318
Acfboy楼主2020/7/22 15:24

RT。

最近在学树链剖分,写了模板又来写这道(这不也是模板吗),结果又写错了,求教。

#include <cstdio>
#include <iostream>
using namespace std;
typedef long long ll;
ll vet[60005], head[30005], nxt[60005], num, cost[30005], numa,
    deep[30005], fa[30005], size[30005], top[30005], treemax[120005], 
    treesum[120005], pos[30005], a[30005], son[30005], n, m, R, P, x, y, z;
char q[10];
void add(ll u, ll v){
    num ++;
    vet[num] = v;
    nxt[num] = head[u];
    head[u]  = num;
}
void dfs(ll u, ll fat, ll dep){
    deep[u] = dep;
    fa[u] = fat;  
    size[u] = 1;
    ll maxson = 0, sonn = 0;
    for(int i = head[u]; i; i = nxt[i]){
        ll v = vet[i];
        if(v == fat) continue;
        dfs(v, u, dep+1);
        size[u] += size[v];
        if(size[v] > maxson){
            maxson = size[v];
            sonn = v;
        }
    }
    son[u] = sonn;
}
void DFS(ll u, ll fat, ll number){
    top[u] = number;
    numa ++; 
    a[numa] = cost[u];
    pos[u] = numa;
    if(son[u] == 0) return;
    DFS(son[u], u, number);
    for(int i = head[u]; i; i = nxt[i]){
        ll v = vet[i];
        if(v == fat || v == son[u]) continue;
        DFS(v, u, v);
    }
}
void maketree(ll p, ll l, ll r){
    if(l == r){
        treesum[p] = a[l]  ;
        treemax[p] = a[l];
        return;
    }
    ll mid = l + (r-l)/2;
    maketree(p+p, l, mid);
    maketree(p+p+1, mid+1, r);
    treesum[p] = treesum[p+p] + treesum[p+p+1];
    treemax[p] = max(treemax[p+p], treemax[p+p+1]);
}
void change(ll p, ll l, ll r, ll x, ll y){
    if(l == r && l == x){
        treesum[p] = y;
        treemax[p] = y;
        a[l] = y;
        return;
    }
    int mid = l + (r-l)/2;
    if(x <= mid) change(p+p, l, mid, x, y);
    else change(p+p+1, mid+1, r, x, y);
    treesum[p] = treesum[p+p] + treesum[p+p+1];
    treemax[p] = max(treemax[p+p], treemax[p+p+1]);
}
ll acc(ll p, ll l, ll r, ll x, ll y){
    if(l == x && r == y) return treesum[p];
    ll mid = l + (r-l)/2;
    if(x > mid) return acc(p+p+1, mid+1, r, x, y);
    else if(y <= mid) return acc(p+p, l, mid, x, y);
    else return acc(p+p, l, mid, x, mid) + acc(p+p+1, mid+1, r, mid+1, y);
}
ll acc2(ll p, ll l, ll r, ll x, ll y){
    if(l == x && r == y) return treemax[p];
    ll mid = l + (r-l)/2;
    if(x > mid) return acc2(p+p+1, mid+1, r, x, y);
    else if(y <= mid) return acc2(p+p, l, mid, x, y);
    else return max(acc2(p+p, l, mid, x, mid), acc2(p+p+1, mid+1, r, mid+1, y));
}
ll findsum(ll u, ll v){
    ll an = 0;
    while(top[u] != top[v]){
        if(deep[top[u]] < deep[top[v]]) swap(u, v);
        an = an + acc(1, 1, n, pos[top[u]], pos[u]);
        u = fa[top[u]];
    }
    if(deep[u] < deep[v]) swap(u, v);
    return (an + acc(1, 1, n, pos[v], pos[u]))  ;
}
ll findmax(ll u, ll v){
    ll an = 0;
    while(top[u] != top[v]){
        if(deep[top[u]] < deep[top[v]]) swap(u, v);
        an = max(an, acc2(1, 1, n, pos[top[u]], pos[u]))  ;
        u = fa[top[u]];
    }
    if(deep[u] < deep[v]) swap(u, v);
    return max(an, acc2(1, 1, n, pos[v], pos[u])) ;
}
int main(){
    scanf("%lld", &n);
    for(int i = 1; i < n; i++){
        scanf("%lld%lld", &x, &y);
        add(x, y);
        add(y, x);
    }
    for(int i = 1; i <= n; i++)
        scanf("%lld", &cost[i]);
    R = 1;
    dfs(1, 0, 1);
    DFS(1, 0, 1);
    maketree(1, 1, n);
    scanf("%lld", &m);
    for(int i = 1; i <= m; i++){
        scanf("%s", q);
        if(q[0] == 'C'){
            scanf("%lld%lld", &x, &y);
            change(1, 1, n, x, y);
        }else if(q[0] == 'Q' && q[1] == 'S'){
            scanf("%lld%lld", &x, &y);
            printf("%lld\n", findsum(x, y));
        }else {
            scanf("%lld%lld", &x, &y);
            printf("%lld\n", findmax(x, y));
        }
    }
    return 0;
}
2020/7/22 15:24
加载中...