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

      功能: 

    修改与查询整个子树

    修改与查询路径 可以时区间和  最大最小值  上同

    求lca 

    #include<bits/stdc++.h>
    using namespace std;
    //input by bxd
    #define rep(i,a,b) for(int i=(a);i<=(b);i++)
    #define repp(i,a,b) for(int i=(a);i>=(b);--i)
    #define RI(n) scanf("%d",&(n))
    #define RII(n,m) scanf("%d%d",&n,&m)
    #define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
    #define RS(s) scanf("%s",s);
    #define ll long long
    #define see(x) (cerr<<(#x)<<'='<<(x)<<endl)
    #define pb push_back
    #define inf 0x3f3f3f3f
    #define CLR(A,v)  memset(A,v,sizeof A)
    #define lson l,m,pos<<1
    #define rson m+1,r,pos<<1|1
    typedef pair<int,int>pii;
    //////////////////////////////////
    const int N=2e6+10;
    const int M=1e6;
    
    int t[N<<2],col[N<<2],w[N],n,mod,m,root,node[N];
    
    void up(int pos)
    {
        t[pos]=t[pos<<1]+t[pos<<1|1];t[pos]%=mod;
    }
    void down(int m,int pos)
    {
        if(col[pos])
        {
            col[pos<<1]+=col[pos];
            col[pos<<1|1]+=col[pos];
            t[pos<<1]+=(m-(m>>1))*col[pos];t[pos<<1]%=mod;
            t[pos<<1|1]+=(m>>1)*col[pos];t[pos<<1|1]%=mod;
            col[pos]=0;
        }
    }
    void build(int l,int r,int pos)
    {
        col[pos]=0;
        if(l==r){t[pos]=w[l]%mod;return ;}//w为重新编号的权值
        int m=(l+r)>>1;
        build(lson);build(rson);
        up(pos);
    }
    void update(int L,int R,int x,int l,int r,int pos)
    {
        if(L<=l&&r<=R)
        {
            t[pos]+=x*(r-l+1);t[pos]%=mod;col[pos]+=x;return ;
        }
        down(r-l+1,pos);
        int m=(l+r)>>1;
        if(L<=m)update(L,R,x,lson);
        if(R>m)update(L,R,x,rson);
        up(pos);
    }
    int query(int L,int R,int l,int r,int pos)
    {
        int ans=0;
        if(L<=l&&r<=R)return t[pos];
        down(r-l+1,pos);
        int m=(l+r)>>1;
        if(L<=m)ans+=query(L,R,lson),ans%=mod;
        if(R>m)ans+=query(L,R,rson),ans%=mod;
        up(pos);
        return ans;
    }
    ///////////////////////////////
    int dep[N],siz[N],fa[N],son[N],head[M],pos,id[N],top[N],cnt;
    struct Edge
    {
        int to,nex;
    }edge[M];
    void add(int a,int b)
    {
        edge[++pos].nex=head[a];
        edge[pos].to=b;
        head[a]=pos;
    }
    void dfs1(int x,int f,int deep)
    {
        dep[x]=deep;
        fa[x]=f;
        siz[x]=1;
        int maxson=-1;
        for(int i=head[x];i;i=edge[i].nex)
        {
            int v=edge[i].to;
            if(v==f)continue;
            dfs1(v,x,deep+1);
            siz[x]+=siz[v];
            if(siz[v]>maxson)maxson=siz[v],son[x]=v;
        }
    }
    void dfs2(int x,int topf)
    {
        id[x]=++cnt;
        w[cnt]=node[x];
        top[x]=topf;
        if(!son[x])return;
        dfs2(son[x],topf);
        for(int i=head[x];i;i=edge[i].nex)
        {
            int v=edge[i].to;
            if(v==fa[x]||v==son[x])continue;
            dfs2(v,v);
        }
    }
    int qrange(int x,int y)//询问x到y最短路径的权值和
    {
        int ans=0;
        while(top[x]!=top[y])
        {
            if(dep[top[x]]<dep[top[y]])swap(x,y);
            ans+=query(id[top[x]],id[x],1,n,1);
            ans%=mod;
            x=fa[top[x]];
        }
        if(dep[x]>dep[y])swap(x,y);
        ans=(ans+query(id[x],id[y],1,n,1))%mod;
        return ans;
    }
    void updaterange(int x,int y,int k)//将x 到y的最短路径上加k
    {
        k%=mod;
        while(top[x]!=top[y])
        {
            if(dep[top[x]]<dep[top[y]])swap(x,y);
            update(id[top[x]],id[x],k,1,n,1);
            x=fa[top[x]];
        }
        if(dep[x]>dep[y])swap(x,y);
        update(id[x],id[y],k,1,n,1);
    }
    int qson(int x)//询问以x为根结点的子树去权值和
    {
        return query(id[x],id[x]+siz[x]-1,1,n,1);
    }
    void updateson(int x,int k)//将以x为根结点子树所有点的权值加k
    {
        update(id[x],id[x]+siz[x]-1,k,1,n,1);
    }
    int main()
    {
        cin>>n>>m>>root>>mod;
        rep(i,1,n)RI(node[i]);
        rep(i,1,n-1){int u,v;RII(u,v);add(u,v);add(v,u);}
        dfs1(root,0,1);
        dfs2(root,root);
        build(1,n,1);
        rep(i,1,m)
        {
            int k,x,y,z;RI(k);
            if(k==1)
            {
                RIII(x,y,z);updaterange(x,y,z);
            }
            else if(k==2)
            {
                RII(x,y);printf("%d
    ",qrange(x,y));
            }
            else if(k==3)
            {
                RII(x,y);updateson(x,y);
            }
            else
            {
                RI(x);printf("%d
    ",qson(x));
            }
        }
        return 0;
    }
    View Code
    int getlca(int x,int y)
    {
        while(top[x]!=top[y])
        {
            if(dep[top[x]]<dep[top[y]])swap(x,y);
            x=fa[top[x]];
        }
        return dep[x]<dep[y]?x:y;
    }
    LCA

    大佬总结的非常好

  • 相关阅读:
    php 建立类POST/GET 的HTTP请求
    上传文件
    golang精选100题带答案
    go面试
    golang反射
    go语言中type的几种使用
    写个版本迭代的方法 例如1.0.9 迭代为1.1.0 到10自动往前进1
    压缩文件和解压文件
    go语言中的文件创建,写入,读取,删除
    go面试题
  • 原文地址:https://www.cnblogs.com/bxd123/p/11162416.html
Copyright © 2011-2022 走看看