悬关求调,37pts,码风正常有注释

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

a1874658776 @ 2024-07-25 15:14:08

1,2,3,11 :AC

8,10 :TLE

其余:WA

代码如下:

//#pragma GCC optimize(2)
#include <bits/stdc++.h>

#define INF 0x3f3f3f3f
#define lowbit(x) x&(-x)
#define Mid (left+right)/2
#define Ls i<<1
#define Rs i<<1|1
#define Lson Ls,left,Mid
#define Rson Rs,Mid+1,right
#define For(i,a,b) for(int i=a;i<=b;i++)

using namespace std;
typedef long long ll;

inline int read()
{
    int x = 0, f = 1; char c = getchar();
    while(c < '0' || c > '9') { if(c == '-') f = -f; c = getchar(); }
    while(c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); }
    return x * f;
}

#define maxN 100010
ll n,rt,m,Mod,opt,x,y,z;
ll nums[maxN];//节点值
vector<ll> v[maxN];//存边
ll fa[maxN],dep[maxN],top[maxN],dfn[maxN],no[maxN],hson[maxN],siz[maxN],cnt;
// 父节点 , 深度,当前链顶端节点,线段树中编号,dfn序,重儿子编号,子树大小,dfs计数
struct node//线段树节点
{
    ll l,r,sum,lazytag;
};
node tr[maxN];

void chainsplit_dfs1(ll root,ll father,ll depth)
{
    siz[root]=1;
    fa[root]=father;
    dep[root]=depth;
    if(v[root].empty()) return ;
    ll sonsizemax=0;
    hson[root]=0;
    For(i,0,v[root].size()-1)
    {
        ll nownode=v[root][i];
        if(nownode==father) continue;
        chainsplit_dfs1(nownode,root,depth+1);
        if(siz[nownode]>sonsizemax)
        {
            sonsizemax=siz[nownode];
            hson[root]=nownode;
        }
        siz[root]+=siz[nownode];
    }
    return;
}
void chainsplit_dfs2(ll root,ll topnode)
{
    ++cnt;
    dfn[root]=cnt;
    no[cnt]=root;
    top[root]=topnode;
    if(siz[root]==1) return ;
    chainsplit_dfs2(hson[root],topnode);
    For(i,1,v[root].size()-1)
    {
        ll nownode=v[root][i];
        if(nownode==fa[root]||nownode==hson[root]) continue;
        chainsplit_dfs2(nownode,nownode);
    }
    return;
}
inline void push_up(ll i)
{
    tr[i].sum=(tr[Ls].sum+tr[Rs].sum)%Mod;
    return ;
}
inline void push_down(ll i)
{
    tr[Ls].sum=(tr[Ls].sum+((tr[Ls].r-tr[Ls].l+1)*tr[i].lazytag))%Mod;
    tr[Rs].sum=(tr[Rs].sum+((tr[Rs].r-tr[Rs].l+1)*tr[i].lazytag))%Mod;
    tr[Ls].lazytag=(tr[Ls].lazytag+tr[i].lazytag)%Mod;
    tr[Rs].lazytag=(tr[Rs].lazytag+tr[i].lazytag)%Mod;
    tr[i].lazytag=0;
    return ;
}
void build_segtree(ll i, ll left, ll right)//建树
{
    tr[i].l = left;
    tr[i].r = right;
    tr[i].lazytag = 0;
    if (left == right)
    {
        tr[i].sum = nums[no[left]]%Mod;
        //cout << "build_segtree: leaf node " << i << " sum = " << tr[i].sum << endl;
        return;
    }
    build_segtree(Lson);
    build_segtree(Rson);
    push_up(i);
    //cout << "build_segtree: internal node " << i << " sum = " << tr[i].sum << endl;
    return;
}
void update_seg(ll i, ll left, ll right, ll x)//线段树更新
{
    if (tr[i].r < left || tr[i].l > right) return;
    if (tr[i].l >= left && tr[i].r <= right)
    {
        tr[i].sum = (tr[i].sum + ((tr[i].r - tr[i].l + 1) * x) ) ;
        tr[i].lazytag = (tr[i].lazytag + x) ;
        //cout << "update_seg: node " << i << " updated sum = " << tr[i].sum << " lazytag = " << tr[i].lazytag << endl;
        //cout<<tr[i].l<<"--------"<<tr[i].r<<endl;
        return;
    }
    push_down(i);
    if (tr[Ls].r >= left) update_seg(Ls, left, right, x);
    if (tr[Rs].l <= right) update_seg(Rs, left, right, x);
    push_up(i);
    //cout << "update_seg: node " << i << " sum after push_up = " << tr[i].sum << endl;
    return;
}
ll query_seg(ll i, ll left, ll right)//线段树查询
{
    if (tr[i].r < left || tr[i].l > right) return 0;
    if (tr[i].l >= left && tr[i].r <= right)
    {
        //cout << "query_seg: node " << i << " sum = " << tr[i].sum << endl;
        return tr[i].sum%Mod;
    }
    push_down(i);
    ll tmp = 0;
    if (tr[Ls].r >= left) tmp = (tmp + query_seg(Ls, left, right))%Mod ;
    if (tr[Rs].l <= right) tmp = (tmp + query_seg(Rs, left, right))%Mod ;
    //cout << "query_seg: node " << i << " sum after query = " << tmp << endl;
    return tmp;
}
void update1(ll u,ll v,ll x)//操作1
{
    x%=Mod;
    while(top[u]!=top[v])
    {
        if(dep[top[u]]<dep[top[v]]) swap(u,v);
        //cout<<"update_seg: u:"<<u<<"-"<<no[u]<<" v:"<<v<<"-"<<no[v]<<endl;
        update_seg(1,dfn[top[u]],dfn[u],x);
        u=fa[top[u]];
    }
    if(dep[u]<dep[v]) swap(u,v);
    update_seg(1,dfn[v],dfn[u],x);
    return ;
}
void update2(ll root,ll x)//操作3
{
    x%=Mod;
    update_seg(1,dfn[root],dfn[root]+siz[root]-1,x);
    return ;
}
ll query1(ll u,ll v)//操作2
{
    ll ans=0;
    while(top[u]!=top[v])
    {
        if(dep[top[u]]<dep[top[v]]) swap(u,v);
        ans=(ans+query_seg(1,dfn[top[u]],dfn[u]))%Mod;
        u=fa[top[u]];
    }
    if(dep[u]<dep[v]) swap(u,v);
    ans=(ans+query_seg(1,dfn[v],dfn[u]))%Mod;
    return ans;
}
ll query2(ll root)//操作4
{
    return query_seg(1,dfn[root],dfn[root]+siz[root]-1)%Mod;
}
void init()//dfs,建树
{
    chainsplit_dfs1(rt,0,1);
    cnt=0;
    chainsplit_dfs2(rt,rt);
    build_segtree(1,1,cnt);
    return ;
}
int main()
{
    //ios::sync_with_stdio(false);
    //cin.tie(nullptr);
    n=read(),m=read(),rt=read(),Mod=read();
    For(i,1,n) nums[i]=read();
    For(i,1,n-1)
    {
        x=read(),y=read();
        v[x].push_back(y);
        v[y].push_back(x);
    }
    init();
    For(i,1,m)
    {
        opt=read();
        if(opt==1)
        {
            x=read(),y=read(),z=read();
            update1(x,y,z);
        }
        if(opt==2)
        {
            x=read(),y=read();
            printf("%lld\n",query1(x,y)%Mod);
        }
        if(opt==3)
        {
            x=read(),z=read();
            update2(x,z);
        }
        if(opt==4)
        {
            x=read();
            printf("%lld\n",query2(x)%Mod);
        }
    }
    return 0;
}

调了很久实在找不出问题在哪里awa


|