bzoj 2836 魔法树 —— 树链剖分

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2836

树链剖分裸题;

写码五分钟,调码两小时,RE不断,狂交二十五遍,终于找到一处小细节——易错点!

就是跳 top 时,不是按 dep[x] < dep[y] 交换 x,y,而要按 dep[top[x]] < dep[top[y]] 交换 x,y,否则就跳不到 lca 了!

经验++。

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define mid ((l+r)>>1)
#define ls (x<<1)
#define rs (x<<1|1)
using namespace std;
typedef long long ll;
int const xn=100005;
int n,fa[xn],hd[xn],ct,nxt[xn],to[xn],dfn[xn],tim,siz[xn],son[xn],top[xn],dep[xn];
ll sum[xn<<2],lzy[xn<<2];
char ch[10];
int rd()
{
  int ret=0,f=1; char ch=getchar();
  while(ch<'0'||ch>'9'){if(ch=='-')f=0; ch=getchar();}
  while(ch>='0'&&ch<='9')ret=(ret<<3)+(ret<<1)+ch-'0',ch=getchar();
  return f?ret:-ret;
}
void add(int x,int y){to[++ct]=y; nxt[ct]=hd[x]; hd[x]=ct;}
void dfs(int x)
{
  siz[x]=1; dep[x]=dep[fa[x]]+1;
  for(int i=hd[x],u;i;i=nxt[i])
    {
      dfs(u=to[i]);
      if(siz[u]>siz[son[x]])son[x]=u;
      siz[x]+=siz[u];
    }
}
void dfs2(int x)
{
  dfn[x]=++tim;
  if(son[x])top[son[x]]=top[x],dfs2(son[x]);
  for(int i=hd[x],u;i;i=nxt[i])
    {
      if((u=to[i])==son[x])continue;
      top[u]=u; dfs2(u);
    }
//  ed[x]=tim;
}
void pushdown(int x,int l,int r)
{
  if(!lzy[x])return; 
  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 update(int x,int l,int r,int L,int R,int k)
{
  if(l>=L&&r<=R){sum[x]+=(ll)k*(r-l+1); lzy[x]+=k; return;}
  pushdown(x,l,r); 
  if(mid>=L)update(ls,l,mid,L,R,k);
  if(mid<R)update(rs,mid+1,r,L,R,k);
  sum[x]=sum[ls]+sum[rs];
}
ll query(int x,int l,int r,int L,int R)
{
  if(l>=L&&r<=R)return sum[x];
  pushdown(x,l,r); ll ret=0;
  if(mid>=L)ret+=query(ls,l,mid,L,R);
  if(mid<R)ret+=query(rs,mid+1,r,L,R);
  return ret;
}
void add(int x,int y,int d)
{
  while(top[x]!=top[y])
    {
      if(dep[top[x]]<dep[top[y]])swap(x,y);//!!!!!
      update(1,1,n,dfn[top[x]],dfn[x],d); x=fa[top[x]];
    }
  if(dep[x]<dep[y])swap(x,y);
  update(1,1,n,dfn[y],dfn[x],d);
}
int main()
{
  n=rd();
  for(int i=1,x,y;i<n;i++)
    {
      x=rd()+1; y=rd()+1;
      fa[y]=x; add(x,y); 
    }
  dfs(1); top[1]=1; dfs2(1);
  int q=rd();
  for(int i=1,u,v,d;i<=q;i++)
    {
      scanf("%s",ch);
      if(ch[0]=='A')
    {
      u=rd()+1; v=rd()+1; d=rd();
      add(u,v,d);
    }
      else u=rd()+1,printf("%lld\n",query(1,1,n,dfn[u],dfn[u]+siz[u]-1));    
    }
  return 0;
}

 

posted @ 2018-10-16 23:36  Zinn  阅读(139)  评论(0编辑  收藏  举报