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;
}

 

posted on 2018-07-11 20:01  Narh  阅读(157)  评论(0编辑  收藏  举报

导航