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

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #define LL long long
    #define l(x) (x<<1)
    #define r(x) ((x<<1)|1)
    using namespace std;
    struct EDG
    {
        int to,nex;
    }es[1000010];
    int n,m,r,p;
    int first[100010];
    int cnt; 
    void link(int a,int b)
    {
        es[++cnt].nex=first[a];
        first[a]=cnt;
        es[cnt].to=b;
    }
    LL a[1000100];
    //树剖↓
    LL real[1000010],sid[1000010],hson[1000010],fa[1000010],dep[1000010],size[1000010],top[1000010];
    LL tot;
    void dfs1(int x)
    {
        size[x]=1;
        for(int i=first[x];i;i=es[i].nex)
        {
            int v=es[i].to;
            if(v!=fa[x])
            {
                fa[v]=x;
                dep[v]=dep[x]+1;
                dfs1(v);
                if(hson[x]==0||size[hson[x]]<size[v])
                {
                    hson[x]=v;
                }
                size[x]+=size[v];
            }
        }
    }
    void dfs2(int x,int anc)
    {
        top[x]=anc;
        sid[x]=++tot;
        real[tot]=x;
        if(hson[x]==0) return;
        dfs2(hson[x],anc);
        for(int i=first[x];i;i=es[i].nex)
        {
            int v=es[i].to;
            if(v!=hson[x]&&v!=fa[x])
            {
                dfs2(v,v);
            }
        }
    }
    //树剖↑ 
    //线段树 ↓ 
    struct Tre
    {
        LL sum,tag;
    }Tr[1000100];
    void update(LL id)
    {
        Tr[id].sum=Tr[l(id)].sum+Tr[r(id)].sum;
    }
    void pushdown(LL l,LL r,LL id)
    {
        Tr[r(id)].tag+=Tr[id].tag;
        Tr[l(id)].tag+=Tr[id].tag;
        Tr[id].sum+=(r-l+1)*Tr[id].tag;
        Tr[id].tag=0;
    }
    void build(LL l,LL r,LL id)
    {
        if(l==r)
        {
            Tr[id].sum=a[real[l]];
            return;
        }
        LL mid=(l+r)/2;
        build(mid+1,r,r(id));
        build(l,mid,l(id));
        update(id);
    }
    void add(LL al,LL ar,LL x,LL l,LL r,LL id)
    {
        if(l>ar||r<al) return;
        if(al==l&&ar==r) {Tr[id].tag+=x;return;}
        pushdown(l,r,id);
        LL mid=(r+l)/2;
        if(mid>=al) add(al,min(mid,ar),x,l,mid,l(id));
        if(mid<ar) add(max(mid+1,al),ar,x,mid+1,r,r(id));
        pushdown(l,mid,l(id));
        pushdown(mid+1,r,r(id));
        update(id);
    }
    LL query(LL al,LL ar,LL l,LL r,LL id)
    {
        if(l>r) return 0LL;
        if(al==l&&ar==r) {return Tr[id].tag*(r-l+1)+Tr[id].sum;}
        pushdown(l,r,id);
        LL mid=(r+l)/2;
        LL t=0;
        if(mid>=al) t+=query(al,min(mid,ar),l,mid,l(id));
        if(mid<ar) t+=query(max(mid+1,al),ar,mid+1,r,r(id));
        return t;
    }
    //线段树 ↑ 
    //树剖用线段树维护↓
    void tr_add(LL x,LL v)//x点及其子孙权值加v 
    {
        add(sid[x],sid[x]+size[x]-1,v,1,n,1);
    }
    LL tr_query(LL x)//x点及其子孙权值和 
    {
        return query(sid[x],sid[x]+size[x]-1,1,n,1)%p;
    }
    LL chain_add(LL x,LL y,LL v)//x到y的链上每个点加v 
    {
        LL tx,ty;
        tx=top[x];ty=top[y];
        while(tx!=ty)
        {
            if(dep[tx]<dep[ty])
            {
                swap(x,y);
                swap(tx,ty);    
            }
            add(sid[tx],sid[x],v,1,n,1);
            x=fa[tx];tx=top[x];    
        }
        if(dep[x]<dep[y]) swap(x,y);
        add(sid[y],sid[x],v,1,n,1);    
    } 
    LL chain_query(LL x,LL y)//查询x到y的链上权值和 
    {
        LL tx,ty,t=0;
        tx=top[x];ty=top[y];
        while(tx!=ty)
        {
            if(dep[tx]<dep[ty]) {swap(tx,ty);swap(x,y);}
            (t+=query(sid[tx],sid[x],1,n,1))%=p;
            x=fa[tx];tx=top[x];
        }
        if(dep[x]<dep[y]) swap(x,y);
        (t+=query(sid[y],sid[x],1,n,1))%=p;
        return t;
    }
    //树剖用线段树维护↑ 
    int main()
    {
        scanf("%d%d%d%d",&n,&m,&r,&p);
        for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
        for(int i=1;i<n;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            link(x,y);link(y,x);
        }
        dep[r]=1;
        dfs1(r);
        dfs2(r,r);
        build(1,n,1);
        for(int i=1;i<=m;i++)
        {
            int q;
            scanf("%d",&q);
            if(q==1)
            {
                LL x,y,z;
                scanf("%lld%lld%lld",&x,&y,&z);
                chain_add(x,y,z);
            }
            if(q==2)
            {
                LL x,y;
                scanf("%lld%lld",&x,&y);
                cout<<chain_query(x,y);
                cout<<endl;
            }
            if(q==3)
            {
                LL x,z;
                scanf("%lld%lld",&x,&z);
                tr_add(x,z);
            }
            if(q==4)
            {
                LL x;
                scanf("%lld",&x);
                cout<<tr_query(x);
                cout<<endl;
            }
        }
    }
    树链剖分模板
  • 相关阅读:
    缅怀我的第一台平板——Surface RT
    【万里征程——Windows App开发】DatePicker&Timepicker
    【万里征程——Windows App开发】用浮出控件做预览效果
    【万里征程——Windows App开发】应用栏
    【万里征程——Windows App开发】画笔和图像
    【万里征程——Windows App开发】绘制图形
    稻香
    【万里征程——Windows App开发】动画1
    【SICP练习】152 练习4.8
    【SICP练习】151 练习4.7
  • 原文地址:https://www.cnblogs.com/wjxgy/p/7834767.html
Copyright © 2011-2022 走看看