【BZOJ4034】【HAOI2015】树上操作
题目请自行查阅传送门。
典型的树剖题,线段树维护操作,记一下子树在线段树内范围即可。
时间复杂度:\( O(m \log^{2} n) \)
#include <stdio.h> #define MN 100005 #define Mn (1<<17) #define ls (k<<1) #define rs (k<<1|1) #define mid (l+r>>1) #define ll long long ll sum[Mn<<1],mark[Mn<<1]; int val[MN],siz[MN],dep[MN],fa[MN],top[MN],son[MN],head[MN],l[MN],r[MN],n,q,cnt,dfsn,root=1; struct tree{int to,nxt;}edge[MN<<1]; inline int in(){ int x=0,f=1; char ch=getchar(); while (ch<'0'||ch>'9') f=ch=='-'?-1:1,ch=getchar(); while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar(); return x*f; } inline void ins(int x,int y){edge[++cnt].to=y,edge[cnt].nxt=head[x],head[x]=cnt;} inline void dfs1(int u,int f,int d){ siz[u]=1,dep[u]=d,fa[u]=f; for (register int i=head[u]; i; i=edge[i].nxt) if (edge[i].to!=f){ dfs1(edge[i].to,u,d+1);siz[u]+=siz[edge[i].to]; if (siz[edge[i].to]>siz[son[u]]) son[u]=edge[i].to; } } inline void dfs2(int u,int tp){ top[u]=tp,l[u]=(++dfsn);if (son[u]) dfs2(son[u],tp); for (register int i=head[u]; i; i=edge[i].nxt) if (edge[i].to!=son[u]&&edge[i].to!=fa[u]) dfs2(edge[i].to,edge[i].to); r[u]=dfsn; } inline void pushdown(int k,int l,int r){ if (l==r||!mark[k]) return;register int x=r-l+1; mark[ls]+=mark[k],mark[rs]+=mark[k]; sum[ls]+=(x-(x>>1))*mark[k];sum[rs]+=(x>>1)*mark[k];mark[k]=0; } inline void combine(int k){sum[k]=sum[ls]+sum[rs];} inline void A(int l,int r,int a,int b,int k,int ad){ if (a<=l&&r<=b){mark[k]+=ad;sum[k]+=1ll*ad*(r-l+1);return;} pushdown(k,l,r);if (a<=mid) A(l,mid,a,b,ls,ad); if (b>mid) A(mid+1,r,a,b,rs,ad);combine(k); } inline ll Q(int l,int r,int a,int b,int k){ if (l==a&&r==b) return sum[k];pushdown(k,l,r); if (b<=mid) return Q(l,mid,a,b,ls); if (a>mid) return Q(mid+1,r,a,b,rs); return Q(l,mid,a,mid,ls)+Q(mid+1,r,mid+1,b,rs); } inline ll query(int x){ register ll res=0; while (top[x]!=root) res+=Q(1,n,l[top[x]],l[x],1),x=fa[top[x]]; return res+=Q(1,n,l[root],l[x],1); } void init(){ n=in(),q=in();for (int i=1; i<=n; ++i) val[i]=in(); for (register int i=1; i<n; ++i){ register int x=in(),y=in(); ins(x,y); ins(y,x); } dfs1(root,1,1);dfs2(root,root); for (register int i=1; i<=n; ++i) A(1,n,l[i],l[i],1,val[i]); } void solve(){ while(q--){ register int op=in(),x=in(),ad; if (op^3){ ad=in();if (op&1) A(1,n,l[x],l[x],1,ad); else A(1,n,l[x],r[x],1,ad); }else printf("%lld\n",query(x)); } } int main(){init(); solve(); return 0;}