BZOJ 4034 树上操作
熟练剖分
不想写树剖怎么办QwQ
维护每个点\(Ans\)
操作\(1\)就是子树加
操作\(2\)是操作\(1\)的叠加......
认真分析......
子树加\(dep\)!!!
写个树状数组节省一下码量
(节省了还是100+)
(我选择死亡)
#include <cstdio>
const int MAXN=100111;
int N, M;
int X;
long long op;
long long Ans;
struct Vert{
int FE;
int Dps, Dpr;
int Dep;
long long Val, Sum;
} V[MAXN];
struct Edge{
int x, y, next;
} E[MAXN<<1];
int Ecnt;
void addE(int a, int b){
++Ecnt;
E[Ecnt].x=a;E[Ecnt].y=b;E[Ecnt].next=V[a].FE;V[a].FE=Ecnt;
}
int Dfn[MAXN], DFN;
void DFS(int at, int f=0){
++DFN;
Dfn[DFN]=at;
V[at].Dps=DFN;
for(int k=V[at].FE, to;k>0;k=E[k].next){
to=E[k].y;
if(to==f) continue;
V[to].Dep=V[at].Dep+1;
V[to].Sum=V[at].Sum+V[to].Val;
DFS(to, at);
}
V[at].Dpr=DFN;
}
int lowbit(int a){
return a&(-a);
}
struct Trray{
int L;
long long n[MAXN];
void init(int l){
L=l;
for(int i=0;i<MAXN;++i) n[i]=0LL;
}
long long Ask(int p){
long long ret=0LL;
for(int i=p;i>0;i-=lowbit(i))
ret+=n[i];
return ret;
}
void Update(int l, int r, long long d){
for(int i=l;i<=L;i+=lowbit(i)) n[i]+=d;
for(int i=r+1;i<=L;i+=lowbit(i)) n[i]-=d;
}
} Cv, Cd;
int main(){
scanf("%d%d", &N, &M);
for(int i=1;i<=N;++i) scanf("%lld", &V[i].Val);
for(int i=1, a, b;i<N;++i){
scanf("%d%d", &a, &b);
addE(a, b);addE(b, a);
}
V[1].Dep=1;
V[1].Sum=V[1].Val;
DFS(1);
Cv.init(DFN);Cd.init(DFN);
for(int t;M--;){
scanf("%d", &t);
if(t==1){
scanf("%d%lld", &X, &op);
Cv.Update(V[X].Dps, V[X].Dpr, op);
}
if(t==2){
scanf("%d%lld", &X, &op);
Cd.Update(V[X].Dps, V[X].Dpr, op);
Cv.Update(V[X].Dps, V[X].Dpr, -op*(long long)(V[X].Dep-1));
}
if(t==3){
scanf("%d", &X);
Ans=V[X].Sum;
Ans+=Cv.Ask(V[X].Dps);
Ans+=Cd.Ask(V[X].Dps)*(long long)(V[X].Dep);
printf("%lld\n", Ans);
}
}
return 0;
}
/*
5 5
1 2 3 4 5
1 2
1 4
2 3
2 5
3 3
1 2 1
3 5
2 1 2
3 3
6
9
13
*/