Wannafly Camp 2020 Day 2F 采蘑菇的克拉莉丝

如果暴力维护,每次询问时需要对所有孩子做计算

考虑通过树剖来平衡修改与询问的时间,询问时计算重链和父树,轻链的贡献预先维护好,修改时则需要修改可能影响的轻链贡献,因为某个点到根的路径上轻重交替只有 (O(log n)) 个,所以只需要修改这么多次,于是复杂度有保证,树状数组维护子树即可

我真是个憨憨,打错树剖调一晚,地上蛙血一大摊

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1e6+5;

int ar[N]; // index: 1 ~ N
int lowbit(int t) { return t & (-t); }
void add(int i, int v) {
	for (; i < N; ar[i] += v, i += lowbit(i));
}
void add(int i, int j, int v) {
    add (j+1, -v);
    add (i, v);
}
int sum(int i) {
	int s = 0;
	for (; i > 0; s += ar[i], i -= lowbit(i));
	return s;
}

vector <pair<int,int> > g[N];
int n,m,t1,t2,t3,pos;
int fa[N],siz[N],f[N],cnt[N],wson[N],len[N],dfn[N],top[N],ind,tot;

void dfs1(int p) {
    siz[p]=1;
    for(pair<int,int> pr:g[p]) {
        int q=pr.first, w=pr.second;
        if(q==fa[p]) continue;
        fa[q]=p;
        len[q]=w;
        dfs1(q);
        siz[p]+=siz[q];
        if(siz[q]>siz[wson[p]]) wson[p]=q;
    }
}

void dfs2(int p) {
    dfn[p]=++ind;
    if(wson[p]) {
        top[wson[p]]=top[p];
        dfs2(wson[p]);
    }
    for(pair<int,int> pr:g[p]) {
        int q=pr.first, w=pr.second;
        if(q==fa[p]) continue;
        if(q==wson[p]) continue;
        top[q]=q;
        dfs2(q);
    }
}

void modify(int v,int x) {
    cnt[v]+=x;
    //v=fa[v];
    while(v) {
        int t=top[v];
        add(dfn[t],dfn[v],x);
        f[fa[t]]+=x*len[t];
        v=fa[t];
    }
    f[0]=0;
}

int query(int p) {
    int ans=0;
    ans+=sum(dfn[wson[p]])*len[wson[p]];
    ans+=f[p];
    ans+=len[p]*(tot-sum(dfn[p]));
    //cout<<sum(dfn[wson[p]])<<"*"<<len[wson[p]]<<" + "<<
    //f[p]<<" + "<<len[p]<<"*"<<(tot-sum(dfn[p]))<<" = "<<ans<<endl;
    return ans;
}

signed main() {
    scanf("%lld",&n);
    for(int i=1;i<n;i++) {
        scanf("%lld%lld%lld",&t1,&t2,&t3);
        g[t1].push_back(make_pair(t2,t3));
        g[t2].push_back(make_pair(t1,t3));
    }
    dfs1(1);
    top[1]=1;
    dfs2(1);
    pos=1;
    scanf("%lld",&m);
    for(int i=1;i<=m;i++) {
        scanf("%lld%lld",&t1,&t2);
        if(t1==1) scanf("%lld",&t3), tot+=t3;
        if(t1==1) modify(t2,t3);
        else pos=t2;
        printf("%lld
",query(pos));
    }
}
原文地址:https://www.cnblogs.com/mollnn/p/12327951.html