操作 1 :把某个节点 x 的点权增加 a 。
操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a 。
操作 3 :询问某个节点 x 到根的路径中所有点的点权和。
//点修改+树修改,(点->根)链查询 #include<bits/stdc++.h> #define ll long long #define rint register int using namespace std; const int N=1e6+5; int n,m,root,cnt,tim; int h[N],be[N],en[N],dep[N]; ll d[N],s1[N],s2[N],size[N],s[N]; struct edge { int v,nxt; } e[N<<1]; inline ll read() { ll x=0; bool flag=false; char ch=getchar(); while(ch<'0'||ch>'9') { if(ch=='-') flag=true; ch=getchar(); } while(ch>='0'&&ch<='9') { x=(x<<3)+(x<<1)+(ch^48); ch=getchar(); } return flag?~x+1:x; } void add_edge(int u,int v) { e[++cnt].v=v; e[cnt].nxt=h[u]; h[u]=cnt; } void dfs(int u,int fat) { dep[u]=dep[fat]+1; be[u]=++tim; size[u]+=d[u];//记录到根节点的距离 for(rint i=h[u];i;i=e[i].nxt) { int v=e[i].v; if(v!=fat) { size[v]+=size[u]; dfs(v,u); } } en[u]=tim; } void add(int x,ll c) { if (x==0) return ; for (rint i=x;i<=n;i+=(i&(-i))) { s[i]+=c; } } void add1(int x,ll c)//处理s1 记录v的变化 { if(x==0) return; for(rint i=x;i<=n;i+=(i&(-i))) s1[i]+=c; } void add2(int x,ll c)//处理s2 记录dep的乘积 { if(x==0) return; for(rint i=x;i<=n;i+=(i&(-i))) s2[i]+=c; } ll sum(int x) { ll ans=0; for(rint i=x;i;i-=(i&(-i))) { ans+=s[i]; } return ans; } ll sum1(int x)//求v的和 { ll ans=0; for(rint i=x;i;i-=(i&(-i))) ans+=s1[i]; return ans; } ll sum2(int x)//求乘积的和 { ll ans=0; for(rint i=x;i;i-=(i&(-i))) ans+=s2[i]; return ans; } int main() { n=read(),m=read(),root=1; for(rint i=1;i<=n;++i) d[i]=read(); for(rint i=1;i<n;++i) { int x=read(),y=read(); add_edge(x,y); add_edge(y,x); } dfs(root,0); for(rint i=1;i<=m;++i) { int op=read();//(deep[y]-deep[x]+1)*v=v*(deep[y]+1)-v*deep[x] if(op==1) { int x=read();ll w=read(); add(be[x],w);add(en[x]+1,-w);//差分记录v } if(op==2) { int x=read();ll w=read(); add1(be[x],w);add1(en[x]+1,-w);//差分记录v add2(be[x],dep[x]*w);add2(en[x]+1,-dep[x]*w);//差分记录dep*v } if(op==3) { int a=read(); ll ans=size[a];//先加上原数据 ans+=((dep[a]+1)*sum1(be[a])-sum2(be[a]));//子树修改求和 ans+=sum(be[a]);//点修改求和 printf("%lld\n",ans); } } } /* in 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 out 6 9 13 */
标签:P3178,ch,int,题解,点权,dfs,操作,节点 From: https://www.cnblogs.com/smghj/p/16914218.html