zoukankan      html  css  js  c++  java
  • 树链剖分模板

    最近好像掉进什么奇怪的数据结构坑里去了。。。。

    先放个板子,讲解和例题到时候在补上

    # include<cstring>
    # include<iostream>
    # include<cstdio>
    # include<cmath>
    # include<cstdio>
    # include<algorithm>
    
    using std::swap;
    const int mn = 200005;
    
    struct edge{int to,next;};
    edge e[mn*2];
    int head[mn],edge_max;
    int n,m,r,mod;
    int val[mn],w[mn];
    int deep[mn],siz[mn],fa[mn];
    int id[mn],bl[mn],tot;
    struct tree{int l,r,sum,lazy;};
    tree  tr[mn*4];
    void add(int x,int y)
    {
        e[++edge_max].to=y;
        e[edge_max].next=head[x];
        head[x]=edge_max;
    }
    void dfs1(int x)
    {
        siz[x]=1;
        for(int i=head[x];i;i=e[i].next)
        {
            int u=e[i].to;
            if(u!=fa[x])
            {
                deep[u]=deep[x]+1;
                fa[u]=x;
                dfs1(u);
                siz[x]+=siz[u];
            }
        }
    }
    void dfs2(int x,int chain)
    {
        int k=0;
        id[x]=++tot;
        w[tot]=val[x];
        bl[x]=chain;
        for(int i=head[x];i;i=e[i].next)
        {
            int u=e[i].to;
            if(deep[u]>deep[x] && siz[u]>siz[k])
                k=u;
        }
        if(!k)
            return ;
        dfs2(k,chain);
        for(int i=head[x];i;i=e[i].next)
        {
            int u=e[i].to;
            if(deep[u]>deep[x] && u!=k)
                dfs2(u,u);
        }
    }
    void build(int l,int r,int cur)
    {
        tr[cur].l=l,tr[cur].r=r;
        if(l==r)
        {
            tr[cur].sum=(w[l])%mod;
            return ;
        }
        int mid=l+r>>1;
        build(l,mid,cur<<1);
        build(mid+1,r,cur<<1|1);
        tr[cur].sum=(tr[cur<<1].sum+tr[cur<<1|1].sum)%mod;
    }
    void pushdown(int cur)
    {
        if(tr[cur].lazy!=0)
        {
            tr[cur<<1].sum=(tr[cur<<1].sum+(tr[cur<<1].r-tr[cur<<1].l+1)*tr[cur].lazy)%mod;
            tr[cur<<1|1].sum=(tr[cur<<1|1].sum+(tr[cur<<1|1].r-tr[cur<<1|1].l+1)*tr[cur].lazy)%mod;
            tr[cur<<1].lazy=(tr[cur<<1].lazy+tr[cur].lazy)%mod;
            tr[cur<<1|1].lazy=(tr[cur<<1|1].lazy+tr[cur].lazy)%mod;
            tr[cur].lazy=0;
        }
        return ;
    }
    void update(int cur,int L,int R,int x)
    {
        if(tr[cur].l>R || tr[cur].r<L)
            return ;
        if(tr[cur].l>=L && tr[cur].r<=R)
        {
            tr[cur].sum=((tr[cur].r-tr[cur].l+1)*x+tr[cur].sum)%mod;
            tr[cur].lazy=(tr[cur].lazy+x)%mod;
            return ;
        }
        pushdown(cur);
        update(cur<<1,L,R,x);
        update(cur<<1|1,L,R,x);
        tr[cur].sum=(tr[cur<<1].sum+tr[cur<<1|1].sum)%mod;
    }
    void treeadd(int x,int y,int z)
    {
        while(bl[x]!=bl[y])
        {
            if(deep[bl[x]]<deep[bl[y]])
                swap(x,y);
            update(1,id[bl[x]],id[x],z);
            x=fa[bl[x]];
        }
        if(deep[x]>deep[y])
           swap(x,y);
        update(1,id[x],id[y],z);
    }
    int query(int cur,int L,int R)
    {
        if(tr[cur].l>=L && tr[cur].r<=R)
            return tr[cur].sum;
        if(tr[cur].l>R || tr[cur].r<L)
            return 0;
        pushdown(cur);
        int ans=0;
        ans=query(cur<<1,L,R);
        ans+=query(cur<<1|1,L,R);
        tr[cur].sum=(tr[cur<<1].sum+tr[cur<<1|1].sum)%mod;
        ans=ans%mod;
        return ans;
    }
    void treesum(int x,int y)
    {
        int ret=0;
        while(bl[x]!=bl[y])
        {
            if(deep[bl[x]]<deep[bl[y]])
                swap(x,y);
            ret=(ret+query(1,id[bl[x]],id[x]))%mod;
            x=fa[bl[x]];
        }
        if(deep[x]>deep[y])
            swap(x,y);
        ret=(ret+query(1,id[x],id[y]))%mod;
        printf("%d
    ",ret);
    }
    int main()
    {
       int x,y,opt,z;
       scanf("%d%d%d%d",&n,&m,&r,&mod);
       for(int i=1;i<=n;i++)
         scanf("%d",&val[i]);
       for(int i=1;i<n;i++)
       {
           scanf("%d%d",&x,&y);
           add(x,y),add(y,x);
       }
       deep[r]=1;
       dfs1(r);
       dfs2(r,r);
       build(1,n,1);
       for(int i=1;i<=m;i++)
       {
          scanf("%d%d",&opt,&x);
          if(opt==1)
          {
              scanf("%d%d",&y,&z);
              treeadd(x,y,z%mod);
          }
          else if(opt==2)
          {
              scanf("%d",&y);
              treesum(x,y);
          }
          else if(opt==3)
          {
              scanf("%d",&y);
              update(1,id[x],id[x]+siz[x]-1,y%mod);
          }
          else {
            printf("%d
    ",query(1,id[x],id[x]+siz[x]-1));
          }
       }
       return 0;
    }
  • 相关阅读:
    webservice 测试窗体只能用于来自本地计算机的请求
    未能加载文件或程序集system.web.extensions解决方法
    VS2010中水晶报表应用及实例
    存储过程
    Windows下wamp的配置问题(php初学者必看!!)
    IIS附加进程在Visual Studio 2010 中进行调试(高级)
    求职之(1)各公司待遇~~可能有点老了
    编译原理之(2)C++词法文件,语法文件
    STL笔记(4)关于erase,remove
    STL笔记(6)标准库:标准库中的排序算法
  • 原文地址:https://www.cnblogs.com/logeadd/p/8918672.html
Copyright © 2011-2022 走看看