求救!!!
查看原帖
求救!!!
225862
LINK_LJM楼主2020/6/8 16:17
#include<bits/stdc++.h>
#define LL long long
#define pii pair<LL,int>
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
const int maxn=1e5+5;
const int inf=0x3f3f3f3f;

struct TMD{
    int to,next;
}edge[maxn<<1];
int head[maxn],cnt,knt,n,m,r;
int f[maxn],deep[maxn],sz[maxn],sn[maxn];
int tree[maxn],pre[maxn],top[maxn],val[maxn];
LL sum[maxn<<2],p,lazy[maxn<<2];
void add(int from,int to){
    edge[++cnt]={to,head[from]};
    head[from]=cnt;
}
void dfs1(int now,int fa){
    deep[now]=deep[fa]+1;
    f[now]=fa;
    sz[now]=1;
    for(int i=head[now];~i;i=edge[i].next){
        int to=edge[i].to;
        if(to==fa) continue;
        dfs1(to,now);
        sz[now]+=sz[to];
        if(!sn[now]||sz[sn[now]]<sz[to]) sn[now]=to;
    }
}
void dfs2(int now,int fa,int tp){
    tree[now]==++knt;pre[knt]=now;
    top[now]=tp;
    if(!sn[now]) return ;
    dfs2(sn[now],now,tp);
    for(int i=head[now];~i;i=edge[i].next){
        int to=edge[i].to;
        if(to==fa||to==sn[now]) continue;
        dfs2(to,now,to);
    }
}
void build(int l,int r,int rt){
    lazy[rt]=0;
    if(l==r) {
        sum[rt]=val[pre[l]]%p;return ;
    }
    int mid=(l+r)>>1;
    build(l,mid,rt<<1);
    build(mid+1,r,rt<<1|1);
    sum[rt]=(sum[rt<<1]+sum[rt<<1|1])%p;
}
void pushdown(int l,int r,int rt){
    int mid=(l+r)>>1;
    if(lazy[rt]){
        lazy[rt<<1]=(lazy[rt<<1]+lazy[rt])%p;
        lazy[rt<<1|1]=(lazy[rt<<1|1]+lazy[rt])%p;
        sum[rt<<1]=(sum[rt<<1]+1ll*(mid-l+1)*lazy[rt]%p)%p;
        sum[rt<<1|1]=(sum[rt<<1|1]+1ll*(r-mid)*lazy[rt]%p)%p;
        lazy[rt]=0;
    }
}
void modify(int L,int R,int l,int r,int rt,int k){
    if(L<=l&&R>=r){
        lazy[rt]+=k;
        sum[rt]=(sum[rt]+1ll*(r-l+1)*k)%p;return ;
    }
    pushdown(l,r,rt);
    int mid=(l+r)>>1;
    if(L<=mid) modify(L,R,l,mid,rt<<1,k);
    if(R>mid) modify(L,R,mid+1,r,rt<<1|1,k);
    sum[rt]=(sum[rt<<1]+sum[rt<<1|1])%p;
}
LL dfs_sum1(int L,int R,int l,int r,int rt){
    if(L<=l&&R>=r) return sum[rt];
    pushdown(l,r,rt);
    int mid=(l+r)>>1;
    LL ans=0;
    if(L<=mid) ans=(ans+dfs_sum1(L,R,l,mid,rt<<1))%p;
    if(R>mid) ans=(ans+dfs_sum1(L,R,mid+1,r,rt<<1|1))%p;
    return ans;
}
LL get_sum(int x,int y){
    int f1=top[x],f2=top[y];
    LL ans=0;
    while(f1!=f2){
        if(deep[f1]<deep[f2]) swap(f1,f2),swap(x,y);
        ans=(ans+dfs_sum1(tree[f1],tree[x],1,n,1))%p;
        x=f[f1],f1=top[x];
    }
    if(deep[x]<deep[y]) swap(x,y);
    ans=(ans+dfs_sum1(tree[y],tree[x],1,n,1))%p;
    return ans;
}
void dfs_sum2(int x,int y,int k){
    int f1=top[x],f2=top[y];
    while(f1!=f2){
        if(deep[f1]<deep[f2]) swap(f1,f2),swap(x,y);
        modify(tree[f1],tree[x],1,n,1,k);
        x=f[f1],f1=top[x];
    }
    if(deep[x]<deep[y]) swap(x,y);
    modify(tree[y],tree[x],1,n,1,k);
}
int main(){
    mem(head,-1);
    int u,v,w,opt;
    scanf("%d%d%d%lld",&n,&m,&r,&p);
    for(int i=1;i<=n;i++) scanf("%d",&val[i]);
    for(int i=1;i<n;i++){
        scanf("%d%d",&u,&v);
        add(u,v);add(v,u);
    }
    dfs1(r,0);
    dfs2(r,0,r);
    build(1,n,1);
    for(int i=1;i<=m;i++) {
        scanf("%d", &opt);
        if(opt==1){
            scanf("%d%d%d",&u,&v,&w);
            dfs_sum2(u,v,w);
        }
        else if(opt==2){
            scanf("%d%d",&u,&v);
            printf("%lld\n",get_sum(u,v));
        }
        else if(opt==3){
            scanf("%d%d",&u,&v);
            modify(tree[u],tree[u]+sz[u]-1,1,n,1,v);
        }
        else {
            scanf("%d",&u);
            printf("%lld\n",dfs_sum1(tree[u],tree[u]+sz[u]-1,1,n,1));
        }
    }
    return 0;
}
2020/6/8 16:17
加载中...