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

    树链剖分常见题型:

    一般对树上路径进行修改或者查询树上一段路径的值的和这类题可以用树链剖分,

    树链剖分一般与线段树结合使用。

    模板题:

    https://www.luogu.com.cn/problem/P3384

    参考博客:

    https://www.cnblogs.com/ivanovcraft/p/9019090.html

    代码:

    #include <bits/stdc++.h>
    #define ls node<<1,l,mid
    #define rs node<<1|1,mid+1,r
    using namespace std;
    const int MAXN=2e5+5;
    int n,m,r,mod;
    int head[MAXN],tot;
    int a[MAXN],val[MAXN];
    struct node
    {
        int to,nxt;
    }e[MAXN<<1];
    void add(int x,int y)
    {
        e[tot].to=y,e[tot].nxt=head[x],head[x]=tot++;
    }
    void add_edge(int x,int y)
    {
        add(x,y);add(y,x);
    }
    int dep[MAXN],f[MAXN],top[MAXN],sz[MAXN],son[MAXN],id[MAXN],cnt;
    void dfs1(int u,int fa)
    {
        dep[u]=dep[fa]+1;sz[u]=1;f[u]=fa;
        for(int i=head[u];~i;i=e[i].nxt)
        {
            int v=e[i].to;
            if(v!=f[u])
            {
                dfs1(v,u);
                sz[u]+=sz[v];
                if(sz[v]>sz[son[u]])
                    son[u]=v;
            }
        }
    }
    void dfs2(int u,int t)
    {
        top[u]=t;id[u]=++cnt;a[cnt]=val[u];
        if(son[u])
            dfs2(son[u],t);
        for(int i=head[u];~i;i=e[i].nxt)
        {
            int v=e[i].to;
            if(v!=f[u]&&v!=son[u])
                dfs2(v,v);
        }
        return;
    }
    int tree[MAXN<<2],lazy[MAXN<<2];
    void push_up(int node)
    {
        tree[node]=tree[node<<1]+tree[node<<1|1];tree[node]%=mod;
    }
    void build(int node,int l,int r)
    {
        if(l==r)
        {
            tree[node]=a[l];return;
        }
        int mid=(l+r)>>1;
        build(ls);build(rs);
        push_up(node);
    }
    void push_down(int node,int l,int r,int mid)
    {
        if(lazy[node])
        {
            tree[node<<1]+=lazy[node]*(mid-l+1);tree[node<<1]%=mod;
            tree[node<<1|1]+=lazy[node]*(r-mid);tree[node<<1|1]%=mod;
            lazy[node<<1]+=lazy[node];lazy[node<<1]%=mod;
            lazy[node<<1|1]+=lazy[node];lazy[node<<1|1]%=mod;
            lazy[node]=0;
        }
    }
    void update(int node,int l,int r,int x,int y,int k)
    {
        if(l>=x&&r<=y)
        {
            lazy[node]+=k;lazy[node]%=mod;tree[node]+=(r-l+1)*k;tree[node]%=mod;
            return ;
        }
        int mid=(l+r)>>1;
        push_down(node,l,r,mid);
        if(x<=mid)
            update(ls,x,y,k);
        if(y>mid)
            update(rs,x,y,k);
        push_up(node);
    }
    int query(int node,int l,int r,int x,int y)
    {
        if(l>=x&&r<=y)
            return tree[node]%mod;
        int mid=(l+r)>>1;
        push_down(node,l,r,mid);
        int ans=0;
        if(x<=mid)
            ans+=query(ls,x,y),ans%=mod;
        if(y>mid)
            ans+=query(rs,x,y),ans%=mod;
        push_up(node);
        return ans%mod;
    }
    void tree_update(int x,int y,int z)
    {
        int fx=top[x],fy=top[y];
        while(fx!=fy)
        {
            if(dep[fx]<dep[fy])swap(x,y),swap(fx,fy);
            update(1,1,cnt,id[fx],id[x],z);
            x=f[fx],fx=top[x];
        }
        if(id[x]>id[y])swap(x,y);
        update(1,1,cnt,id[x],id[y],z);
    }
    int tree_sum(int x,int y)
    {
        int res=0;
        int fx=top[x],fy=top[y];
        while(fx!=fy)
        {
            if(dep[fx]<dep[fy])swap(x,y),swap(fx,fy);
            res+=query(1,1,cnt,id[fx],id[x]),res%=mod;
            x=f[fx],fx=top[x];
        }
        if(id[x]>id[y])swap(x,y);
        res+=query(1,1,cnt,id[x],id[y]),res%=mod;
        res%=mod;
        return res;
    }
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        memset(head,-1,sizeof(head));
        cin>>n>>m>>r>>mod;
        for(int i=1;i<=n;i++)
            cin>>val[i];
        for(int i=1;i<n;i++)
        {
            int x,y;cin>>x>>y;add_edge(x,y);
        }
        dfs1(r,0);dfs2(r,r);
        build(1,1,n);
        while(m--)
        {
            int op,x,y,z;
            cin>>op;
            if(op==1)
            {
                cin>>x>>y>>z;tree_update(x,y,z);
            }
            if(op==2)
            {
                cin>>x>>y;cout<<tree_sum(x,y)<<endl;
            }
            if(op==3)
            {
                cin>>x>>z;update(1,1,n,id[x],id[x]+sz[x]-1,z);
            }
            if(op==4)
            {
                cin>>x;cout<<query(1,1,n,id[x],id[x]+sz[x]-1)<<endl;
            }
        }
        return 0;
    }
  • 相关阅读:
    四,awk格式化
    printf命令详解
    三,awk变量
    二,awk分隔符
    一,AWK基础
    【leetcode_easy_array】1399. Count Largest Group
    【leetcode_easy_array】1184. Distance Between Bus Stops
    【leetcode_easy_array】1346. Check If N and Its Double Exist
    【leetcode_easy_array】1304. Find N Unique Integers Sum up to Zero
    【leetcode_easy_array】1337. The K Weakest Rows in a Matrix
  • 原文地址:https://www.cnblogs.com/ljxdtc666/p/12589594.html
Copyright © 2011-2022 走看看