【洛谷P3384】 树链剖分模板

Ahead

10.5.2018 第一篇文章 欢迎指正

分析

树链剖分模板题,如果有时间的话在上树剖算法分析吧
这道大紫题
剖完(切完拉完。。。。)
然后加上线段树维护

  • 注意下标的处理(在映射之间傻傻分不清)
  • 查询和更新直接沿着边跑
  • 对于子树是序列加大小
  • 带了快读自动忽略
  • dfs1 用于保存树的信息
  • dfs2 来连接太子
    努力憋文字摘要不能有代码! ! !

    代码

#include <bits/stdc++.h>
using namespace std;

inline int read()
{
  int x=0,f=1;
  char c=getchar();
  while(c<'0' || c>'9')
  {
    if(c=='-') f=-1;
    c=getchar();
  }
  while(c<='9' && c>='0')
  {
    x=(x<<1)+(x<<3)+c-'0';
    c=getchar();
  }
  return x*f;
}

const int N = 1e5+100;
int n,m,root,mod;
int w[N];

int to[N<<1],nxt[N<<1],last[N],len;
inline void ins(int x,int y)
{
  to[++len]=y, nxt[len]=last[x], last[x]=len;
}

int tot[N],dep[N],son[N],fa[N];
void dfs1(int x)
{
  tot[x]=1;
  for(int k=last[x]; k; k=nxt[k])
  {
    int y=to[k];
    if(y!=fa[x])
    {
      dep[y]=dep[x]+1;
      fa[y]=x;
      dfs1(y);
      tot[x]+=tot[y];
      if(tot[y]>tot[son[x]]) son[x]=y;
    }
  }
}

int pos[N],top[N],rpos[N],tim;
void dfs2(int x,int tp)
{
  pos[x]=++tim, rpos[tim]=x, top[x]=tp;
  if(!son[x]) return;
  dfs2(son[x],tp);
  for(int k=last[x]; k; k=nxt[k])
  {
    int y=to[k];
    if(y!=fa[x] && y!=son[x]) dfs2(y,y);
  }
}

struct node
{
  int l,r,val,lazy;
} e[N<<2];

inline void push_up(int now)
{
  e[now].val=(e[now<<1].val+e[now<<1|1].val)%mod;
}

inline void push_down(int now)
{
  e[now<<1].val+=e[now].lazy*(e[now<<1].r-e[now<<1].l+1);
  e[now<<1].val%=mod;
  e[now<<1].lazy+=e[now].lazy;
  e[now<<1|1].val+=e[now].lazy*(e[now<<1|1].r-e[now<<1|1].l+1);
  e[now<<1|1].val%=mod;
  e[now<<1|1].lazy+=e[now].lazy;
  e[now].lazy=0;
}

void bt(int now ,int l,int r)
{
  e[now].l=l,e[now].r=r;
  if(l>=r)
  {
    e[now].val=w[rpos[l]];
    return ;
  }
  int mid=(l+r)>>1;
  bt(now<<1,l,mid);
  bt(now<<1|1,mid+1,r);
  push_up(now);
}

void up_data(int now ,int l,int r,int k)
{
  if(e[now].l==l && e[now].r==r)
  {
    e[now].val+=k*(r-l+1);
    e[now].val%=mod;
    e[now].lazy+=k;
    return;
  }
  if(e[now].lazy) push_down(now);
  int mid=(e[now].l+e[now].r)>>1;
  if(r<=mid) up_data(now<<1,l,r,k);
  else if(l>mid) up_data(now<<1|1,l,r,k);
  else
  {
    up_data(now<<1,l,mid,k);
    up_data(now<<1|1,mid+1,r,k);
  }
  push_up(now);
}

int quary(int now ,int l,int r)
{
  if(e[now].l==l && e[now].r==r) return e[now].val;
  int ans=0;
  if(e[now].lazy) push_down(now);
  int mid=(e[now].l+e[now].r)>>1;
  if(r<=mid) ans=quary(now<<1,l,r)%mod;
  else if(l>mid) ans=quary(now<<1|1,l,r)%mod;
  else
  {
    ans+=quary(now<<1,l,mid)%mod;
    ans+=quary(now<<1|1,mid+1,r)%mod;
    ans%=mod;
  }
  push_up(now);
  return ans;
}

inline void updata(int x,int y,int k)
{
  int tx=top[x],ty=top[y];
  while(tx!=ty)
  {
    if(dep[tx]>dep[ty]) swap(x,y),swap(tx,ty);
    up_data(1,pos[ty],pos[y],k);
    y=fa[ty],ty=top[y];
  }
  if(dep[x]>dep[y]) swap(x,y);
  up_data(1,pos[x],pos[y],k);
}

inline int ask(int x,int y)
{
  int ans=0,tx=top[x],ty=top[y];
  while(tx!=ty)
  {
    if(dep[tx]>dep[ty]) swap(x,y),swap(tx,ty);
    ans+=quary(1,pos[ty],pos[y]);
    ans%=mod;
    y=fa[ty],ty=top[y];
  }
  if(dep[x]>dep[y]) swap(x,y);
  ans+=quary(1,pos[x],pos[y])%mod;
  ans%=mod;
  return ans;
}

int main()
{
  int q,x,y,c;
  n=read(),m=read(),root=read(),mod=read();
  for(int i=1; i<=n; ++i) w[i]=read();
  for(int i=1; i<n; ++i)
  {
    x=read(),y=read();
    ins(x,y);
    ins(y,x);
  }
  dep[root]=1;
  dfs1(root);
  dfs2(root,root);
  /*for(int i=1; i<=n; ++i)
    printf("ddd %d\n",fa[i]);
  system("pause");*/
  bt(1,1,tim);
  while(m--)
  {
    q=read();
    if(q==1)
    {
      x=read(),y=read(),c=read();
      updata(x,y,c);
    }
    else if(q==2)
    {
      x=read(),y=read();
      printf("%d\n",ask(x,y)%mod);
    }
    else if(q==3)
    {
      x=read(),y=read();
      up_data(1,pos[x],pos[x]+tot[x]-1,y);
    }
    else if(q==4)
    {
      x=read();
      printf("%d\n",quary(1,pos[x],pos[x]+tot[x]-1)%mod);
    }
  }
  return 0;
}

猜你喜欢

转载自www.cnblogs.com/PiCaHor/p/9745802.html