20/30pts 求助
查看原帖
20/30pts 求助
25728
F3_Dy楼主2021/8/2 19:58
#include<iostream>
#include<cstdio>
#include<vector>
#define int long long
using namespace std;
int n,m,r,p,cnt;
vector<int>e[100010];
int val[100010];
int sz[100010],fa[100010],d[100010],hs[100010],id[100010],rk[100010],tp[100010];
int ad[400010],vl[400010];
void dfs1(int x)
{
    sz[x]=1;
    d[x]=d[fa[x]]+1;
    hs[x]=-1;
    for(int i=0;i<e[x].size();i++)
    {
        if(e[x][i]!=fa[x])
        {
            fa[e[x][i]]=x;
            dfs1(e[x][i]);
            sz[x]+=sz[e[x][i]];
            if(hs[x]==-1||sz[hs[x]]<sz[e[x][i]])
            {
                hs[x]=e[x][i];
            }
        }
    }
}
void dfs2(int x,int top)
{
    tp[x]=top;
    id[x]=++cnt;
    rk[cnt]=x;
    if(hs[x]==-1)
    {
        return;
    }
    dfs2(hs[x],top);
    for(int i=0;i<e[x].size();i++)
    {
        if(e[x][i]!=fa[x]&&e[x][i]!=hs[x])
        {
            dfs2(e[x][i],e[x][i]);
        }
    }
}
void add(int o,int l,int r,int il,int ir,int iv)
{
    if(il>ir)
    {
        swap(il,ir);
    }
    if(l>=il&&r<=ir)
    {
        ad[o]=(ad[o]+iv)%p;
    }
    else
    {
        if(il<=(l+r>>1))
        {
            add(o<<1,l,(l+r>>1),il,ir,iv);
        }
        if(ir>(l+r>>1))
        {
            add((o<<1)^1,(l+r>>1)+1,r,il,ir,iv);
        }
    }
    vl[o]=0;
    if(l<r)
    {
        vl[o]=(vl[o<<1]+vl[(o<<1)^1])%p;
    }
    vl[o]=(vl[o]+(r-l+1)*ad[o]%p)%p;
}
int query(int o,int l,int r,int il,int ir,int sv)
{
    if(il>ir)
    {
        swap(il,ir);
    }
    if(l>=il&&r<=ir)
    {
        return (vl[o]+sv*(r-l+1))%p;
    }
    int cn=0;
    if(il<=(l+r>>1))
    {
        cn+=query(o<<1,l,(l+r>>1),il,ir,sv+ad[o]);
    }
    if(ir>(l+r>>1))
    {
        cn+=query((o<<1)^1,(l+r>>1)+1,r,il,ir,sv+ad[o]);
    }
    return cn%p;
}
void treeadd(int l,int r,int v)
{
    while(tp[l]!=tp[r])
    {
        if(d[l]<d[r])
        {
            swap(l,r);
        }
        add(1,1,n,id[tp[l]],id[l],v);
        l=fa[tp[l]];
    }
    if(d[l]>d[r])
    {
        swap(l,r);
    }
    add(1,1,n,id[l],id[r],v);
}
int treeask(int l,int r)
{
    int cnt=0;
    while(tp[l]!=tp[r])
    {
        if(d[l]<d[r])
        {
            swap(l,r);
        }
        cnt+=query(1,1,n,id[tp[l]],id[l],0);
        l=fa[tp[l]];
    }
    if(d[l]>d[r])
    {
        swap(l,r);
    }
    cnt+=query(1,1,n,id[l],id[r],0);
    return cnt%p;
}
signed main()
{
    cin>>n>>m>>r>>p;
    for(int i=1;i<=n;i++)
    {
        cin>>val[i];
    }
    for(int i=1;i<n;i++)
    {
        int u,v;
        cin>>u>>v;
        e[u].push_back(v);
        e[v].push_back(u);
    }
    fa[r]=r;
    dfs1(r);
    dfs2(r,r);
    for(int i=1;i<=n;i++)
    {
        add(1,1,n,id[i],id[i],val[i]);
    }
    for(int i=1;i<=m;i++)
    {
        int op;
        cin>>op;
        if(op==1)
        {
            int x,y,z;
            cin>>x>>y>>z;
            treeadd(x,y,z);
        }
        if(op==2)
        {
            int x,y;
            cin>>x>>y;
            cout<<treeask(x,y)<<endl;
        }
        if(op==3)
        {
            int x,y;
            cin>>x>>y;
            add(1,1,n,id[x],id[x]+sz[x]-1,y);
        }
        if(op==4)
        {
            int x;
            cin>>x;
            cout<<query(1,1,n,id[x],id[x]+sz[x]-1,0)<<endl;
        }
    }
    return 0;
}

2021/8/2 19:58
加载中...