• 树链剖分


    What?

                 熟练泼粪这又是一种十分神奇的数据结构,由于博主认为自身实力不行,所以不敢随便BB,上一个大佬级别的链接,超级清楚!Problem

    不随便BB(既然不能随便BB,那只好不随便了)

    依本博主看,树链剖分就是将一棵漂亮的树,解剖成一条条树链,然后使用线段树进行维护,从而解决一系列问题。

    只要理解了树链剖分中各种新有名词的含义及特点,那么树链剖分便十分的简单。

    有同学说:“什么?用线段树维护,那不是很变态?”没错,不过线段树算什么?引某位大佬早上对我说的一句话:“我们要把线段树当成STL来用。”%%%

    Code

    本博主由于懒,所以没打链式前向星(其实是不会啊),不过vector真好用啊。

    #include<cstdio>
    #include<vector>
    #include<algorithm>
    #define MAXN 100010
    #define UD unsigned
    using namespace std;
    
    int n,m,r,Mod,cnt,ans;
    int init[MAXN],cor[MAXN];
    UD sl[MAXN];
    vector<int> rel[MAXN];
    struct CHAIN
    {
        int id;
        int fa;
        int zhi;
        int size;
        int deep;
        int Max_son;
        int top;
    }chain[MAXN];
    struct TREE
    {
        int l,r;
        int zhi;
        int lazy;
    }tree[MAXN*8];
    
    void Pushdown(int k)
    {
        tree[k<<1].zhi+=(tree[k<<1].r-tree[k<<1].l+1)*tree[k].lazy;
        tree[k<<1].zhi%=Mod; 
        tree[k<<1].lazy+=tree[k].lazy;
        tree[k<<1].lazy%=Mod;
        tree[k<<1|1].zhi+=(tree[k<<1|1].r-tree[k<<1|1].l+1)*tree[k].lazy;
        tree[k<<1|1].zhi%=Mod;
        tree[k<<1|1].lazy+=tree[k].lazy;
        tree[k<<1|1].lazy%=Mod;
        tree[k].lazy=0;
    }
    
    void Build(int L,int R,int k)
    {
        int Mid=(L+R)>>1;
        tree[k].l=L,tree[k].r=R;
        if(L==R)
        {
            tree[k].zhi=chain[cor[L]].zhi%=Mod;
            return;
        }
        Build(L,Mid,k<<1);
        Build(Mid+1,R,k<<1|1);
        tree[k].zhi=tree[k<<1].zhi+tree[k<<1|1].zhi;
        tree[k].zhi%=Mod;
    }
    
    void Update(int L,int R,int k,int s,int t,int x)
    {
        int Mid=(L+R)>>1;
        Pushdown(k);
        if(s<=L && R<=t)
        {
            tree[k].zhi+=(tree[k].r-tree[k].l+1)*x;
            tree[k].lazy+=x;
            tree[k].zhi%=Mod;
            tree[k].lazy%=Mod;
            return;
        }
        if(s<=Mid)
            Update(L,Mid,k<<1,s,t,x);
        if(Mid<t)
            Update(Mid+1,R,k<<1|1,s,t,x);
        tree[k].zhi=tree[k<<1].zhi+tree[k<<1|1].zhi;
        tree[k].zhi%=Mod;
    }
    
    void Query(int L,int R,int k,int s,int t)
    {
        int Mid=(L+R)>>1;
        Pushdown(k);
        if(s<=L && R<=t)
        {
            ans+=tree[k].zhi;
            ans%=Mod;
            return;
        }
        if(s<=Mid)
            Query(L,Mid,k<<1,s,t);
        if(Mid<t)
            Query(Mid+1,R,k<<1|1,s,t);
            
    }
    
    void Dfs1(int x,int f,int dep)
    {
        int MAX=0;
        chain[x].fa=f,chain[x].deep=dep,chain[x].size=1,chain[x].zhi=init[x]%=Mod;
        for(UD i=0;i<sl[x];i++)
        {
            if(rel[x][i]==chain[x].fa)
                continue;
            Dfs1(rel[x][i],x,dep+1);
            if(chain[rel[x][i]].size>MAX)
                MAX=chain[rel[x][i]].size,chain[x].Max_son=rel[x][i];
            chain[x].size+=chain[rel[x][i]].size;
        }
    }
    
    void Dfs2(int x,int topf)
    {
        chain[x].id=++cnt;
        cor[cnt]=x,chain[x].top=topf;
        if(!chain[x].Max_son)
            return;
        Dfs2(chain[x].Max_son,topf);
        for(UD i=0;i<sl[x];i++)
        {
            if(rel[x][i]==chain[x].fa || rel[x][i]==chain[x].Max_son)
                continue;
            Dfs2(rel[x][i],rel[x][i]);
        }
    }
    
    void Update_chain(int x,int y,int z)
    {
        while(chain[x].top!=chain[y].top)
        {
            if(chain[chain[x].top].deep<chain[chain[y].top].deep)
                swap(x,y);
            Update(1,n,1,chain[chain[x].top].id,chain[x].id,z);
            x=chain[chain[x].top].fa;
        }
        if(chain[x].deep>chain[y].deep)
            swap(x,y);
        Update(1,n,1,chain[x].id,chain[y].id,z);
    }
    
    void Query_chain(int x,int y)
    {
        ans=0;
        while(chain[x].top!=chain[y].top)
        {
            if(chain[chain[x].top].deep<chain[chain[y].top].deep)
                swap(x,y);
            Query(1,n,1,chain[chain[x].top].id,chain[x].id);
            x=chain[chain[x].top].fa;
        }
        if(chain[x].deep>chain[y].deep)
            swap(x,y);
        Query(1,n,1,chain[x].id,chain[y].id);
    }
    
    void Update_tree(int x,int z)
    <%Update(1,n,1,chain[x].id,chain[x].id+chain[x].size-1,z);%>
    
    void Query_tree(int x)
    {
        ans=0;
        Query(1,n,1,chain[x].id,chain[x].id+chain[x].size-1);
    }
    
    int main()
    {
        int opt,x,y,z;
        scanf("%d%d%d%d",&n,&m,&r,&Mod);
        for(int i=1;i<=n;i++)
            scanf("%d",&init[i]);
        for(int i=1;i<n;i++)
        {
            scanf("%d%d",&x,&y);
            rel[x].push_back(y);
            rel[y].push_back(x);  
        }
        for(int i=1;i<=n;i++)
            sl[i]=rel[i].size();
        Dfs1(r,0,1);
        Dfs2(r,r);
        Build(1,n,1);
        for(int i=1;i<=m;i++)
        {
            scanf("%d",&opt);
            if(opt==1)
            {
                scanf("%d%d%d",&x,&y,&z);
                Update_chain(x,y,z);
            }
            if(opt==2)
            {
                scanf("%d%d",&x,&y);
                Query_chain(x,y);
                printf("%d
    ",ans%Mod);
            }
            if(opt==3)
            {
                scanf("%d%d",&x,&z);
                Update_tree(x,z);
            }
            if(opt==4)
            {
                scanf("%d",&x);
                Query_tree(x);
                printf("%d
    ",ans%Mod);
            }
        }
        return 0;
    }

    码量不过200行+

  • 相关阅读:
    19.08.12 知识点的记录
    19.08.09 知识点的记录
    keil编译生成bin文件的方法
    python 虚拟环境virtualenv
    RT_Thread GD32F303 片上flash使用fal组件
    esp8266 deepsleep唤醒不工作打印
    5V 电源 适配器 空载耗电量 自身电量 消耗功率
    keil 更换jlink脚本版本
    ESP8266 NONOS SmartConfig配网(安信可公众号配网)
    windows安装esp开发环境
  • 原文地址:https://www.cnblogs.com/Thm-V/p/11311316.html
Copyright © 2020-2023  润新知