求助长链剖分&hack(玄2关)

P3384 【模板】重链剖分/树链剖分

CQBZ_ZJYjoe @ 2024-09-01 11:07:58

我怀疑我写了一个假的长链剖分。

#include<bits/stdc++.h>
#define int long long
#define INT LONG_LONG
#define fast_io ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define lowbit(x) x&-x
using namespace std;
int n,m,r,p,idd[100005],sd[100005],fa[100005],top[100005],son[100005],b[100005],a[100005],siz[100005],tot;
struct Node
{
    int d,l,r,tag,siz;
}tree[400005];
vector<signed> edges[100005];
inline void push_data(int x)
{
    tree[x*2].d=(tree[x*2].d+tree[x].tag*tree[x*2].siz)%p;
    tree[x*2+1].d=(tree[x*2+1].d+tree[x].tag*tree[x*2+1].siz)%p;
    tree[x*2].tag=(tree[x*2].tag+tree[x].tag)%p;
    tree[x*2+1].tag=(tree[x*2+1].tag+tree[x].tag)%p;
    tree[x].tag=0;
}
inline void make_tree(int x,int l,int r)
{
    tree[x].l=l,tree[x].r=r,tree[x].siz=r-l+1;
    if (l==r)
    {
        tree[x].d=a[l]%p;
        return ;
    }
    make_tree(x*2,l,(l+r)>>1),make_tree(x*2+1,((l+r)>>1)+1,r);
    tree[x].d=(tree[x*2].d+tree[x*2+1].d)%p;
}
inline void change(int x,int l,int r,int k)
{
    if (tree[x].l>=l&&tree[x].r<=r)
    {
        tree[x].d=(tree[x].d+k*tree[x].siz)%p;
        tree[x].tag=(tree[x].tag+k)%p;
        return ;
    }
    push_data(x);
    int mid=(tree[x].l+tree[x].r)>>1;
    if (mid>=l)
        change(x*2,l,r,k);
    if (mid<r)
        change(x*2+1,l,r,k);
    tree[x].d=(tree[x*2].d+tree[x*2+1].d)%p;
}
inline int ask(int x,int l,int r)
{
    if (tree[x].l>=l&&tree[x].r<=r)
        return (tree[x].d)%p;
    push_data(x);
    int sum=0,mid=(tree[x].l+tree[x].r)>>1;
    if (mid>=l)
        sum=(sum+ask(x*2,l,r))%p;
    if (mid<r)
        sum=(sum+ask(x*2+1,l,r))%p;
    return sum;
}
inline void tree_change(int x,int y,int k)
{
    while (top[x]!=top[y])
    {
        if (sd[top[x]]<sd[top[y]])
            swap(x,y);
        change(1,idd[top[x]],idd[x],k);
        x=fa[top[x]];
    }
    if (sd[x]>sd[y])
        swap(x,y);
    change(1,idd[x],idd[y],k);
}
inline int tree_ask(int x,int y)
{
    int sum=0;
    while (top[x]!=top[y])
    {
        if (sd[top[x]]<sd[top[y]])
            swap(x,y);
        sum=(sum+ask(1,idd[top[x]],idd[x]))%p;
        x=fa[top[x]];
    }
    if (sd[x]>sd[y])
        swap(x,y);
    sum=(sum+ask(1,idd[x],idd[y]))%p;
    return sum;
}
inline void dfs_1(int x,int faa,int sdd)
{
    fa[x]=faa;
    son[x]=0;
    sd[x]=sdd;
    siz[x]=1;
    int max_son=-1;
    for (auto i:edges[x])
    {
        if (i==faa)
            continue;
        dfs_1(i,x,sdd+1);
        siz[x]+=siz[i];
        if(sd[i]>max_son)
            son[x]=i,max_son=sd[i];
    }
}
inline void dfs_2(int x,int to)
{
    top[x]=to;
    idd[x]=++tot;
    a[idd[x]]=b[x];
    if (!son[x])
        return ;
    dfs_2(son[x],to);
    for (auto i:edges[x])
    {
        if (i==fa[x]||i==son[x])
            continue;
        dfs_2(i,i);
    }
}
signed main()
{
    fast_io;
    cin>>n>>m>>r>>p;
    for (int i=1;i<=n;i++)
        cin>>b[i];
    for (int i=1;i<n;i++)
    {
        int u,v;
        cin>>u>>v;
        edges[u].push_back(v),edges[v].push_back(u);
    }
    dfs_1(r,0,1);
    dfs_2(r,r);
    make_tree(1,1,n);
    for (int i=1;i<=m;i++)
    {
        int op,x,y,z;
        cin>>op;
        if (op==1)
        {
            cin>>x>>y>>z;
            tree_change(x,y,z);
        }
        else if (op==2)
        {
            cin>>x>>y;
            cout<<tree_ask(x,y)<<endl;
        }
        else if (op==3)
        {
            cin>>x>>z;
            change(1,idd[x],idd[x]+siz[x]-1,z);
        }
        else 
        {
            cin>>x;
            cout<<ask(1,idd[x],idd[x]+siz[x]-1)<<endl;
        }
    }
    return 0;
}

因为他比重链剖分还快0.07s。

但是

请各位大佬帮帮我。


by Union_Find @ 2024-09-01 11:16:42

数据水吧,也不会有什么人写长链剖分,就没有卡了。


by xudongyi1 @ 2024-09-01 11:18:33

我唐了qwq


by CQBZ_ZJYjoe @ 2024-09-01 11:18:41

@xudongyi1 我是用的深度更新啊


|