树链剖分板子(c++)

常规:

struct slpf
{
    const int nn;
    struct node
    {
        int l, r, tag;
        int val;
    };
    vector<node> tr;
    vector<int> fa, dep, son, siz, top, dfn, w;
    vector<int> v;
    vector<vector<int>> g;
    int tim;
    slpf(int n1) : nn(n1), tr((n1 + 10) << 2), fa(n1 + 1), dep(n1 + 1), son(n1 + 1, 0), siz(n1 + 1), top(n1 + 1), dfn(n1 + 1), w(n1 + 1), v(n1 + 1), g(n1 + 1), tim(0) {}
    void add(int uu, int vv)
    {
        g[uu].push_back(vv);
    }
    void dfs1(int now, int fr)
    {
        fa[now] = fr;
        dep[now] = dep[fr] + 1;
        siz[now] = 1;
        int max_size = -1;
        for (int x : g[now])
        {
            if (x == fr)
                continue;
            dfs1(x, now);
            siz[now] += siz[x];
            if (siz[x] > max_size)
            {
                max_size = siz[x];
                son[now] = x;
            }
        }
    }
    void dfs2(int now, int tp)
    {
        dfn[now] = ++tim;
        top[now] = tp;
        w[tim] = v[now];
        if (!son[now])
            return;
        dfs2(son[now], tp);
        for (int x : g[now])
        {
            if (x == fa[now] || x == son[now])
                continue;
            dfs2(x, x);
        }
    }
    void build(int root, int l, int r) //根节点为1,范围从1-n
    {
        tr[root].l = l;
        tr[root].r = r;
        tr[root].tag = 0; // add的初始值为0
        if (l == r)
        {
            tr[root].val = w[l]; //初始值
            return;
        }
        int mid = (l + r) >> 1;
        build(root << 1, l, mid);
        build(root << 1 | 1, mid + 1, r);
        tr[root].val = tr[root << 1].val + tr[root << 1 | 1].val;
    }
    void spread(int p)
    {
        if (tr[p].tag != 0)
        {
            tr[p << 1].val += tr[p].tag * (tr[p << 1].r - tr[p << 1].l + 1);
            tr[p << 1 | 1].val += tr[p].tag * (tr[p << 1 | 1].r - tr[p << 1 | 1].l + 1);
            tr[p << 1].tag += tr[p].tag;
            tr[p << 1 | 1].tag += tr[p].tag;
            tr[p].tag = 0;
        }
    }
    void update(int root, int l, int r, int x)
    {
        if (l <= tr[root].l && r >= tr[root].r)
        {
            tr[root].val += x * (tr[root].r - tr[root].l + 1);
            tr[root].tag += x;
            return;
        }
        spread(root);
        int mid = (tr[root].l + tr[root].r) >> 1;
        if (l <= mid)
            update(root << 1, l, r, x);
        if (r > mid)
            update(root << 1 | 1, l, r, x);
        tr[root].val = tr[root << 1].val + tr[root << 1 | 1].val;
    }
    int getsum(int root, int l, int r)
    {
        if (l <= tr[root].l && r >= tr[root].r)
            return tr[root].val;
        spread(root);
        int mid = (tr[root].l + tr[root].r) >> 1;
        int ans = 0;
        if (l <= mid)
            ans = (ans + getsum(root << 1, l, r));
        if (r > mid)
            ans = (ans + getsum(root << 1 | 1, l, r));
        return ans;
    }
    void make_tree(int root, vector<int> &arr)
    {
        v = arr;
        dfs1(root, root);
        dfs2(root, root);
        build(1, 1, nn);
    }
    void update_son(int x, int z) // x为根结点的子树所有节点值+z
    {
        update(1, dfn[x], dfn[x] + siz[x] - 1, z);
    }
    int query_son(int x) // x为根结点的子树所有节点值之和
    {
        return getsum(1, dfn[x], dfn[x] + siz[x] - 1);
    }
    void update_chain(int x, int y, int z)
    {
        while (top[x] != top[y])
        {
            if (dep[top[x]] < dep[top[y]])
                swap(x, y);
            update(1, dfn[top[x]], dfn[x], z);
            x = fa[top[x]];
        }
        if (dep[x] > dep[y])
            swap(x, y);
        update(1, dfn[x], dfn[y], z);
    }
    int query_chain(int x, int y)
    {
        int res = 0;
        while (top[x] != top[y])
        {
            if (dep[top[x]] < dep[top[y]])
                swap(x, y);
            res += getsum(1, dfn[top[x]], dfn[x]);
            x = fa[top[x]];
        }
        if (dep[x] > dep[y])
            swap(x, y);
        res += getsum(1, dfn[x], dfn[y]);
        return res;
    }
    void remake_tree(int root)
    {
        fa.assign(nn + 1, 0);
        dep.assign(nn + 1, 0);
        son.assign(nn + 1, 0);
        siz.assign(nn + 1, 0);
        top.assign(nn + 1, 0);
        dfn.assign(nn + 1, 0);
        tim = 0;
        dfs1(root, root);
        dfs2(root, root);
        build(1, 1, nn);
    }
    int lca(int x, int y)
    {
        while (top[x] != top[y])
        {
            if (dep[top[x]] >= dep[top[y]])
                x = fa[top[x]];
            else
                y = fa[top[y]];
        }
        return dep[x] < dep[y] ? x : y;
    }
};

带取模:

struct slpf{
    const int nn;
    struct node{
        int l,r,tag;
        int val;
    };
    vector<node> tr;
    vector<int> fa,dep,son,siz,top,dfn,w;
    vector<int> v;
    vector<vector<int>> g;
    int tim;
    slpf(int n1):nn(n1),tr((n1+10)*4),fa(n1+1),dep(n1+1),son(n1+1,0),siz(n1+1),top(n1+1),dfn(n1+1),w(n1+1),v(n1+1),g(n1+1),tim(0){}
    void add(int uu,int vv)
    {
        g[uu].push_back(vv);
    }
    void dfs1(int now,int fr)
    {
        fa[now]=fr;
        dep[now]=dep[fr]+1;
        siz[now]=1;
        int max_size=-1;
        for(int x:g[now])
        {
            if(x==fr)
                continue;
            dfs1(x,now);
            siz[now]+=siz[x];
            if(siz[x]>max_size)
            {
                max_size=siz[x];
                son[now]=x;
            }
        }
    }
    void dfs2(int now,int tp)
    {
        dfn[now]=++tim;
        top[now]=tp;
        w[tim]=v[now];
        if(!son[now])
            return;
        dfs2(son[now],tp);
        for(int x:g[now])
        {
            if(x==fa[now]||x==son[now])
                continue;
            dfs2(x,x);
        }
    }
    void build(int root,int l,int r)//根节点为1,范围从1-n
    {
        tr[root].l=l;
        tr[root].r=r;
        tr[root].tag=0;//add的初始值为0
        if(l==r)
        {
            tr[root].val=w[l];//初始值
            return;
        }
        int mid=(l+r)/2;
        build(root*2,l,mid);
        build(root*2+1,mid+1,r);
        tr[root].val=tr[root*2].val+tr[root*2+1].val;
    }
    void spread(int p)
    {
        if(tr[p].tag!=0)
        {
            tr[p*2].val+=tr[p].tag*(tr[p*2].r-tr[p*2].l+1);
            tr[p*2+1].val+=tr[p].tag*(tr[p*2+1].r-tr[p*2+1].l+1);
            tr[p*2].tag+=tr[p].tag;
            tr[p*2+1].tag+=tr[p].tag;
            tr[p].tag=0;
        }
    }
    void update(int root,int l,int r,int x)
    {
        if(l<=tr[root].l&&r>=tr[root].r)
        {
            tr[root].val+=x*(tr[root].r-tr[root].l+1);
            tr[root].tag+=x;
            return;
        }
        spread(root);
        int mid=(tr[root].l+tr[root].r)>>1;
        if(l<=mid)
            update(root*2,l,r,x);
        if(r>mid)
            update(root*2+1,l,r,x);
        tr[root].val=tr[root*2].val+tr[root*2+1].val;
    }
    int getsum(int root,int l,int r)
    {
        if(l<=tr[root].l&&r>=tr[root].r)
            return tr[root].val;
        spread(root);
        int mid=(tr[root].l+tr[root].r)>>1;
        int ans=0;
        if(l<=mid)
            ans=(ans+getsum(root*2,l,r));
        if(r>mid)
            ans=(ans+getsum(root*2+1,l,r));
        return ans;
    }
    void make_tree(int root,vector<int> &arr)
    {
        v=arr;
        dfs1(root,root);
        dfs2(root,root);
        build(1,1,nn);
    }
    void remake_tree(int root)
    {
        fa.assign(nn+1,0);
        dep.assign(nn+1,0);
        son.assign(nn+1,0);
        siz.assign(nn+1,0);
        top.assign(nn+1,0);
        dfn.assign(nn+1,0);
        tim=0;
        dfs1(root,root);
        dfs2(root,root);
        build(1,1,nn);
    }
    void update_son(int x,int z)//x为根结点的子树所有节点值+z
    {
        update(1,dfn[x],dfn[x]+siz[x]-1,z);
    }
    int query_son(int x)//x为根结点的子树所有节点值之和
    {
        return getsum(1,dfn[x],dfn[x]+siz[x]-1);
    }
    void update_chain(int x,int y,int z)
    {
        while(top[x]!=top[y])
        {
            if(dep[top[x]]<dep[top[y]])
                swap(x,y);
            update(1,dfn[top[x]],dfn[x],z);
            x=fa[top[x]];
        }
        if(dep[x]>dep[y])
            swap(x,y);
        update(1,dfn[x],dfn[y],z);
    }
    int query_chain(int x,int y)
    {
        int res=0;
        while(top[x]!=top[y])
        {
            if(dep[top[x]]<dep[top[y]])
                swap(x,y);
            res+=getsum(1,dfn[top[x]],dfn[x]);
            x=fa[top[x]];
        }
        if(dep[x]>dep[y])
            swap(x,y);
        res+=getsum(1,dfn[x],dfn[y]);
        return res;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值