求救只有十分(

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

gjh303987897 @ 2023-04-04 09:48:51

#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#include<map>
#include<stack>
#include<stdlib.h>
#include<queue>
#include<climits>

int read(){
    int x=0,f=1; char ch=getchar();
    while(ch>'9'||ch<'0'){ if(ch=='-'){ f=-1; } ch=getchar(); }
    while(ch>='0'&&ch<='9'){ x=(x<<3)+(x<<1)+(ch^48); ch=getchar(); }
    return x*f; 
}

int n,m,r,p;
const int maxn = 1e5+11;
int w[maxn];

struct tree{
    int next;
    int to;
}t[maxn<<1];
int head[maxn<<1],js;
void add(int u,int v){
    t[++js].next=head[u];
    t[js].to=v;
    head[u]=js;
}

int fa[maxn];
int dep[maxn];
int subtree_size[maxn];
int son[maxn];
void dfs1(int now,int father,int deep){
    fa[now]=father;
    dep[now]=deep;
    subtree_size[now]=1;
    int maxx = -1;
    for(int i=head[now];i;i=t[i].next){
        int y = t[i].to;
        if(y==father) continue;
        dfs1(y,now,deep+1);
        subtree_size[now]+=subtree_size[y];
        if(subtree_size[y]>maxx){
            maxx=subtree_size[y];
            son[now]=y;
        }
    }
}

int cnt;
int tree_w[maxn];
int node_id[maxn];
int top[maxn];

void dfs2(int now,int topf){
    node_id[now]=++cnt;
    tree_w[cnt]=w[now];
    top[now]=topf;
    if(!son[now]) return;
    dfs2(son[now],topf);
    for(int i=head[now];i;i=t[i].next){
        int y = t[i].to;
        if(y==son[now]||y==fa[now]) continue;
        dfs2(y,y);
    }
}

int seg_tree[maxn<<2];
int lazy_tag[maxn<<2];
int tree_l[maxn],tree_r[maxn];
void pushdown(int now,int l,int r){
    lazy_tag[now<<1]+=lazy_tag[now];
    lazy_tag[now<<1|1]+=lazy_tag[now];
    seg_tree[now<<1]+=lazy_tag[now]*(tree_r[now<<1]-tree_l[now<<1]+1);
    seg_tree[now<<1|1]+=lazy_tag[now]*(tree_r[now<<1|1]-tree_l[now<<1|1]+1);
    seg_tree[now<<1]%=p;
    seg_tree[now<<1|1]%=p;
    lazy_tag[now]=0;
}   

void build(int now,int l,int r){
    if(l==r){
        seg_tree[now]=tree_w[l]%p;
        tree_l[now]=tree_r[now]=r;
        lazy_tag[now]=0;
        return;
    }
    int mid = (l+r)>>1;
    build(now<<1,l,mid);
    build(now<<1|1,mid+1,r);
    seg_tree[now]=seg_tree[now<<1|1]+seg_tree[now<<1];
    seg_tree[now]%=p;
    tree_l[now]=tree_l[now<<1];
    tree_r[now]=tree_r[now<<1|1];
}

int quary(int now,int l,int r,int q_l,int q_r){
    int ans = 0;
    if(l>=q_l&&r<=q_r){
        ans+=seg_tree[now];
        ans%=p;
        return ans;
    }
    int mid = (l+r)>>1;
    if(lazy_tag[now]) pushdown(now,tree_l[now],tree_r[now]);
    if(q_l<=mid) ans+=quary(now<<1,l,mid,q_l,q_r)%p;
    if(q_r>mid) ans+=quary(now<<1|1,mid+1,r,q_l,q_r)%p;
    return ans%p;
}

void update(int now,int l,int r,int q_l,int q_r,int num){
    if(l>=q_l&&l<=q_r){
        lazy_tag[now]+=num;
        seg_tree[now]+=(r-l+1)*num;
        seg_tree[now]%=p;
        return;
    }
    int mid = (l+r)>>1;
    if(lazy_tag[now]) pushdown(now,tree_l[now],tree_r[now]);
    if(q_l<=mid) update(now<<1,l,mid,q_l,q_r,num);
    if(q_r>mid) update(now<<1|1,mid+1,r,q_l,q_r,num);
    seg_tree[now]=seg_tree[now<<1]+seg_tree[now<<1|1];
    seg_tree[now]%=p;
}

void q_update(int x,int y,int z){
    z%=p;
    while (top[x]!=top[y]){
        if(dep[top[x]]<dep[top[y]]) std:: swap(x,y);
        update(1,1,n,node_id[top[x]],node_id[x],z);
        x=fa[top[x]];
    }
    if(dep[x]<dep[y]) std:: swap(x,y);
    update(1,1,n,node_id[y],node_id[x],z);
}
int q_quary(int x,int y){
    int ans=0;
    while(top[x]!=top[y]){
        if(dep[top[x]]<dep[top[y]]) std:: swap(x,y);
        ans+=quary(1,1,n,node_id[top[x]],node_id[x])%p;
        x=fa[top[x]];
    }
    if(dep[x]<dep[y]) std:: swap(x,y);
    ans+=quary(1,1,n,node_id[y],node_id[x])%p;
    return ans;
}

void q_update_subtree(int x,int z){
    z%=p;
    update(1,1,n,node_id[x],node_id[x]+subtree_size[x]-1,z);
}

int q_quary_subtree(int x){
    return quary(1,1,n,node_id[x],node_id[x]+subtree_size[x]-1)%p;
}   

int main(){
    n=read(),m=read(),r=read(),p=read();
    for(int i=1;i<=n;i++){
        w[i]=read();
    }
    for(int i=1;i<=n-1;i++){
        int x=read(),y=read();
        add(x,y);
        add(y,x);
    }
    dfs1(r,0,1);
    dfs2(r,r);
    build(1,1,n);
    for(int i=1;i<=m;i++){
        int judge=read();
        if(judge==1){
            int x=read(),y=read(),z=read();
            q_update(x,y,z);
        }
        if(judge==2){
            int x=read(),y=read();
            std:: cout<<q_quary(x,y)<<std:: endl;
        }
        if(judge==3){
            int x=read(),z=read();
            q_update_subtree(x,z);
        }
        if(judge==4){
            int x=read();
            std:: cout<<q_quary_subtree(x)<<std:: endl;
        }
    }
    return 0;
}

|