bzoj4034 [HAOI2015]树上操作——树链剖分
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4034
树剖裸题;
一定要注意 long long !!!
update 的时候别忘了 pushdown ...
代码如下:
#include<iostream> #include<cstdio> #include<cstring> using namespace std; typedef long long ll; int const maxn=1e5+5; int n,m,tim,dfn[maxn],id[maxn],top[maxn],son[maxn],siz[maxn],fa[maxn]; int hd[maxn],ct,a[maxn],end[maxn]; ll sum[maxn<<2],lzy[maxn<<2];//ll struct N{ int to,nxt; N(int t=0,int n=0):to(t),nxt(n) {} }ed[maxn<<1]; void add(int x,int y){ed[++ct]=N(y,hd[x]); hd[x]=ct;} void dfs(int x) { siz[x]=1; for(int i=hd[x],u;i;i=ed[i].nxt) { if((u=ed[i].to)==fa[x])continue; fa[u]=x; dfs(u); siz[x]+=siz[u]; if(siz[u]>siz[son[x]])son[x]=u; } } void dfs2(int x) { id[dfn[x]=++tim]=x; if(son[x])top[son[x]]=top[x],dfs2(son[x]); for(int i=hd[x],u;i;i=ed[i].nxt) { if((u=ed[i].to)==fa[x]||u==son[x])continue; top[u]=u; dfs2(u); } end[x]=tim; } void pushup(int x){sum[x]=sum[x<<1]+sum[x<<1|1];} void pushdown(int x,int l,int r) { if(lzy[x]) { int ls=(x<<1),rs=(x<<1|1),mid=((l+r)>>1); sum[ls]+=lzy[x]*(mid-l+1); lzy[ls]+=lzy[x]; sum[rs]+=lzy[x]*(r-mid); lzy[rs]+=lzy[x]; lzy[x]=0; } } void build(int x,int l,int r) { if(l==r){sum[x]=a[id[l]]; return;} int mid=((l+r)>>1); build(x<<1,l,mid); build(x<<1|1,mid+1,r); pushup(x); } ll query(int x,int l,int r,int L,int R) { if(l>=L&&r<=R)return sum[x]; pushdown(x,l,r); int mid=((l+r)>>1); ll ret=0; if(mid>=L)ret+=query(x<<1,l,mid,L,R); if(mid<R)ret+=query(x<<1|1,mid+1,r,L,R); return ret; } void update(int x,int l,int r,int L,int R,ll v)//ll { if(l>=L&&r<=R){sum[x]+=v*(r-l+1); lzy[x]+=v; return;} pushdown(x,l,r);//!!! int mid=((l+r)>>1); if(mid>=L)update(x<<1,l,mid,L,R,v); if(mid<R)update(x<<1|1,mid+1,r,L,R,v); pushup(x); } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)scanf("%d",&a[i]); for(int i=1,x,y;i<n;i++) { scanf("%d%d",&x,&y); add(x,y); add(y,x); } dfs(1); top[1]=1; dfs2(1); build(1,1,n); for(int i=1,p,x;i<=m;i++) { ll v;// scanf("%d%d",&p,&x); if(p==1){scanf("%lld",&v); update(1,1,n,dfn[x],dfn[x],v);} if(p==2){scanf("%lld",&v); update(1,1,n,dfn[x],end[x],v);} if(p==3) { ll ans=0; while(x)// { ans+=query(1,1,n,dfn[top[x]],dfn[x]);//顺序 x=fa[top[x]]; } printf("%lld\n",ans); } } return 0; }