20分求助!
查看原帖
20分求助!
215108
浅梦楼主2020/11/17 18:05
#include <bits/stdc++.h>
#define pb push_back
#define ll long long
#define IOS std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;

const int maxn=100005;
ll n,m,r,p;
ll d[maxn];
struct node
{
    ll next,to,w;
}e[200005];
struct NODE
{
    ll l,r,val,add;
}tree[400005];
ll rp,tot;
ll head[200005],cnt;
ll fa[maxn],dep[maxn],siz[maxn],son[maxn],top[maxn],dfn[maxn],rnk[maxn];
void add(ll u,ll v)
{
    e[cnt].to=v;
    e[cnt].next=head[u];
    head[u]=cnt++;
}
void dfs(ll u,ll f,ll w)
{
    fa[u]=f;
    son[u]=-1;
    siz[u]=1;
    dep[u]=w;//更新节点u深度
    for(int i=head[u];i!=-1;i=e[i].next)
    {
        ll v=e[i].to;
        if(v==f){continue;}
        dfs(v,u,w+1);
        siz[u]+=siz[v];//更新节点u的子树的节点个数
        if(son[u]==-1||siz[son[u]]<siz[son[v]]){son[u]=v;}//更新重儿子
    }
}
void dfs2(ll u,ll tt)
{
    top[u]=tt;
    ++tot;
    dfn[u]=tot;
    rnk[tot]=u;
    if(son[u]==-1){return;}
    dfs2(son[u],tt);
    for(int i=head[u];i!=-1;i=e[i].next)
    {
        ll v=e[i].to;
        if(v==fa[u]){continue;}
        if(v!=son[u])
        {dfs2(v,v);}
    }
}
void build(ll os,ll l,ll r)
{
    tree[os].l=l;
    tree[os].r=r;
    if(l==r)
    {
        tree[os].val=d[rnk[++rp]]%p;
        return;
    }
    ll mid=(l+r)/2;
    build(os*2,l,mid);
    build(os*2+1,mid+1,r);
    tree[os].val=(tree[os*2].val+tree[os*2+1].val)%p;
}
void spread(ll os)
{
    if(tree[os].add)
    {
        tree[os*2].val=(tree[os*2].val+(((tree[os*2].r-tree[os*2].l+1)%p)*(tree[os].add)%p)%p)%p;
        tree[os*2+1].val=(tree[os*2+1].val+(((tree[os*2+1].r-tree[os*2+1].l+1)%p)*(tree[os].add)%p)%p)%p;
        tree[os*2].add=(tree[os*2].add+tree[os].add)%p;
        tree[os*2+1].add=(tree[os*2+1].add+tree[os].add)%p;
        tree[os].add=0;
    }
}
void change(ll os,ll x,ll y,ll z)
{
    if(x<=tree[os].l&&y>=tree[os].r)
    {
        tree[os].val=(tree[os].val+(((tree[os].r-tree[os].l+1)%p)*z%p)%p)%p;
        tree[os].add=(tree[os].add+z)%p;
        return;
    }
    spread(os);
    ll mid=(tree[os].l+tree[os].r)/2;
    if(x<=mid)
    {change(os*2,x,y,z%p);}
    if(y>mid)
    {change(os*2+1,x,y,z%p);}
    tree[os].val=(tree[os*2].val+tree[os*2+1].val)%p;
}
ll query(ll os,ll x,ll y)
{
    if(x<=tree[os].l&&y>=tree[os].r)
    {return tree[os].val;}
    spread(os);
    ll mid=(tree[os].l+tree[os].r)/2;
    ll ans=0;
    if(x<=mid)
    {ans=(ans+query(os*2,x,y))%p;}
    if(y>mid)
    {ans=(ans+query(os*2+1,x,y))%p;}
    return ans%p;
}
void solvec(ll x,ll y,ll z)
{
    ll sx=top[x],sy=top[y];
    while(sx!=sy)
    {
        if(dep[sx]>=dep[sy])
        {
            change(1,dfn[sx],dfn[x],z%p);
            x=fa[sx];
            sx=top[x];
        }
        else
        {
            change(1,dfn[sy],dfn[y],z%p);
            y=fa[sy];
            sy=top[y];
        }
    }
    if(dfn[x]<=dfn[y])
    {change(1,dfn[x],dfn[y],z%p);}
    else
    {change(1,dfn[y],dfn[x],z%p);}
}
ll solveq(ll x,ll y)
{
    ll ans=0;
    ll sx=top[x],sy=top[y];
    while(sx!=sy)
    {
        if(dep[sx]>=dep[sy])
        {
            ans=(ans+query(1,dfn[sx],dfn[x]))%p;
            x=fa[sx];
            sx=top[x];
        }
        else
        {
            ans=(ans+query(1,dfn[sy],dfn[y]))%p;
            y=fa[sy];
            sy=top[y];
        }
    }
    if(dfs[x]<=dfs[y])
    {ans=(ans+query(1,dfn[x],dfn[y]))%p;}
    else
    {ans=(ans+query(1,dfn[y],dfn[x]))%p;}
    return ans;
}
int main()
{
    memset(head,-1,sizeof(head));
    scanf("%lld %lld %lld %lld",&n,&m,&r,&p);
    for(int i=1;i<=n;i++){scanf("%lld",&d[i]);}
    for(int i=1;i<=n-1;i++)
    {
        ll x,y;
        scanf("%lld %lld",&x,&y);
        add(x,y);
        add(y,x);
    }
    dfs(r,r,1);
    dfs2(r,r);
    build(1,1,n);
    while(m--)
    {
        ll x,y,z,op;
        scanf("%lld",&op);
        if(op==1)
        {
            scanf("%lld %lld %lld",&x,&y,&z);
            solvec(x,y,z);
        }
        if(op==2)
        {
            scanf("%lld %lld",&x,&y);
            printf("%lld\n",solveq(x,y));
        }
        if(op==3)
        {
            scanf("%lld %lld",&x,&z);
            change(1,dfn[x],dfn[x]+siz[x]-1,z%p);
        }
        if(op==4)
        {
            scanf("%lld",&x);
            printf("%lld\n",query(1,dfn[x],dfn[x]+siz[x]-1));
        }
    }
    return 0;
}

救救孩子

2020/11/17 18:05
加载中...