树上操作
这是一个初学树剖很好的练手题。
我想我只需要放个代码……
#include<bits/stdc++.h> using namespace std; #define int long long const int maxn=1000000; int n,m; int beg[maxn],nex[maxn],to[maxn],e; inline void add(int x,int y){ e++;nex[e]=beg[x]; beg[x]=e;to[e]=y; } int dep[maxn],f[maxn],son[maxn],size[maxn]; inline void dfs1(int x,int fa){ dep[x]=dep[fa]+1; f[x]=fa; size[x]=1; for(int i=beg[x];i;i=nex[i]){ int t=to[i]; if(t==fa)continue; dfs1(t,x); size[x]+=size[t]; if(size[t]>size[son[x]])son[x]=t; } } int val[maxn],id[maxn],num[maxn],top[maxn],cnt; inline void dfs2(int x,int topc){ id[x]=++cnt; num[cnt]=val[x]; top[x]=topc; if(!son[x])return; dfs2(son[x],topc); for(int i=beg[x];i;i=nex[i]){ int t=to[i]; if(t==f[x]||t==son[x]) continue; dfs2(t,t); } } int tree[maxn],lazy[maxn]; inline void build(int h,int l,int r){ if(l==r){ tree[h]=num[l]; return; } int mid=(l+r)>>1; build(h<<1,l,mid); build(h<<1|1,mid+1,r); tree[h]=tree[h<<1]+tree[h<<1|1]; } inline void pushup(int h,int l,int r,int z){ tree[h]+=(r-l+1)*z; lazy[h]+=z; } inline void pushdown(int h,int l,int r){ if(!lazy[h])return; int mid=(l+r)>>1; pushup(h<<1,l,mid,lazy[h]); pushup(h<<1|1,mid+1,r,lazy[h]); lazy[h]=0; } inline void update(int h,int l,int r,int x,int y,int z){ if(l>y||r<x)return; if(l>=x&&r<=y){ pushup(h,l,r,z); return; } pushdown(h,l,r); int mid=(l+r)>>1; update(h<<1,l,mid,x,y,z); update(h<<1|1,mid+1,r,x,y,z); tree[h]=tree[h<<1]+tree[h<<1|1]; } inline int query(int h,int l,int r,int x,int y){ if(l>y||r<x)return 0; if(l>=x&&r<=y)return tree[h]; pushdown(h,l,r); int mid=(l+r)>>1; return query(h<<1,l,mid,x,y)+query(h<<1|1,mid+1,r,x,y); } inline int qc(int x,int y){ int ans=0; while(top[x]!=top[y]){ if(dep[top[x]]<dep[top[y]])swap(x,y); ans+=query(1,1,n,id[top[x]],id[x]); x=f[top[x]]; } if(dep[x]>dep[y])swap(x,y); ans+=query(1,1,n,id[x],id[y]); return ans; } signed main(){ cin>>n>>m; for(int i=1;i<=n;i++) scanf("%lld",&val[i]); for(int i=1;i<n;i++){ int x,y; scanf("%lld%lld",&x,&y); add(x,y); add(y,x); } dfs1(1,0); dfs2(1,1); build(1,1,n); for(int i=1;i<=m;i++){ int opt; scanf("%lld",&opt); if(opt==1){ int x,a; scanf("%lld%lld",&x,&a); update(1,1,n,id[x],id[x],a); }else if(opt==2){ int x,a; scanf("%lld%lld",&x,&a); update(1,1,n,id[x],id[x]+size[x]-1,a); }else{ int x; scanf("%lld",&x); printf("%lld\n",qc(1,x)); } } return 0; }
深深地感到自己的弱小。