bzoj 4034 [HAOI2015]树上操作——树链剖分
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4034
这么赤裸裸的树剖竟然花了我这么久……
就是因为树剖本来就是dfs序,所以就能弄子树了。每个节点return的时候记录一下表示自己子树的结束。注意这些都是在dfs2里的。
注意各种 long long。
#include<iostream> #include<cstdio> #include<cstring> #define ll long long using namespace std; const int N=1e5+5; int n,m,hd[N],xnt,son[N],siz[N],dfn[N],cq[N],id[N],top[N],fa[N],tim; int ls[N<<1],rs[N<<1];// ll sum[N<<1],lazy[N<<1],len[N<<1],val[N];// struct Ed{ int nxt,to;Ed(int n=0,int t=0):nxt(n),to(t) {} }ed[N<<1]; void add(int x,int y) { ed[++xnt]=Ed(hd[x],y);hd[x]=xnt; ed[++xnt]=Ed(hd[y],x);hd[y]=xnt; } void dfs1(int cr) { siz[cr]=1; for(int i=hd[cr],v;i;i=ed[i].nxt) if((v=ed[i].to)!=fa[cr]) { fa[v]=cr;dfs1(v);siz[cr]+=siz[v]; if(siz[v]>siz[son[cr]])son[cr]=v; } } void dfs2(int cr) { id[dfn[cr]=++tim]=cr;// not in dfs1!!! if(son[cr])top[son[cr]]=top[cr],dfs2(son[cr]); for(int i=hd[cr],v;i;i=ed[i].nxt) if((v=ed[i].to)!=fa[cr]&&v!=son[cr]) top[v]=v,dfs2(v); cq[cr]=tim; } void pshp(int cr) { sum[cr]=sum[ls[cr]]+sum[rs[cr]]; } void build(int l,int r,int cr) { len[cr]=r-l+1; if(l==r) { sum[cr]=val[id[l]];return; } int mid=((l+r)>>1); ls[cr]=++tim;build(l,mid,ls[cr]); rs[cr]=++tim;build(mid+1,r,rs[cr]); pshp(cr); } void pshd(int cr) { if(!lazy[cr])return;int l=ls[cr],r=rs[cr]; ll w=lazy[cr];lazy[cr]=0;lazy[l]+=w;lazy[r]+=w; sum[l]+=len[l]*w;sum[r]+=len[r]*w; } void mdfy(int l,int r,int cr,int p,ll w)//ll { if(l==r){sum[cr]+=w;return;} pshd(cr);//! int mid=((l+r)>>1); if(p<=mid)mdfy(l,mid,ls[cr],p,w); else mdfy(mid+1,r,rs[cr],p,w); pshp(cr); } void mdfy(int l,int r,int cr,int L,int R,ll w)// { if(l>=L&&r<=R){sum[cr]+=len[cr]*w;lazy[cr]+=w;return;} pshd(cr); int mid=((l+r)>>1); if(mid>=L)mdfy(l,mid,ls[cr],L,R,w); if(mid<R)mdfy(mid+1,r,rs[cr],L,R,w); pshp(cr); } ll query(int l,int r,int cr,int L,int R) { if(l>=L&&r<=R)return sum[cr]; pshd(cr); int mid=((l+r)>>1);ll ret=0; if(mid>=L)ret+=query(l,mid,ls[cr],L,R); if(mid<R)ret+=query(mid+1,r,rs[cr],L,R); return ret; } ll query(int x) { ll ret=0; while(x) { ret+=query(1,n,1,dfn[top[x]],dfn[x]); x=fa[top[x]]; } return ret; } int main() { scanf("%d%d",&n,&m);int x,y; for(int i=1;i<=n;i++)scanf("%lld",&val[i]); for(int i=1;i<n;i++) { scanf("%d%d",&x,&y);add(x,y); } dfs1(1);top[1]=1;dfs2(1); tim=1;build(1,n,1); int op;ll w; for(int i=1;i<=m;i++) { scanf("%d%d",&op,&x);if(op!=3)scanf("%lld",&w); if(op==1)mdfy(1,n,1,dfn[x],w); if(op==2)mdfy(1,n,1,dfn[x],cq[x],w); if(op==3)printf("%lld\n",query(x)); } return 0; }