社区讨论

萌新刚学OI两天,树剖求条

P3384【模板】重链剖分 / 树链剖分参与者 3已保存回复 11

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
11 条
当前快照
1 份
快照标识符
@mhjkspxs
此快照首次捕获于
2025/11/04 04:11
4 个月前
此快照最后确认于
2025/11/04 06:31
4 个月前
查看原帖
CPP
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+2;
int n,m,r,a[N],mod;
int deep[N],dfn[N],son[N],siz[N],top[N],fa[N];
int to[N<<1],nxt[N<<1],head[N],cnt;
int newa[N],tr[N<<2],tag[N<<2];
void addtag(int p,int pl,int pr,int d){
    tag[p]+=d;
    tr[p]+=d*(pr-pl+1);tr[p]%=mod;
}
void pushdown(int p,int pl,int pr){
    if(tag[p]){
        int d=tag[p];
        tag[p<<1]+=d,tag[p<<1|1]+=d;
        int mid=(pl+pr)>>1;
        tr[p<<1]+=d*(mid-pl+1),tr[p<<1|1]+=d*(pr-mid);
        tr[p<<1]%=mod,tr[p<<1|1]%=mod;
        tag[p]=0;
    }
}
void build(int i,int l,int r){
    if(l==r){
        tag[i]=newa[l];
        return;
    }
    int mid=(l+r)>>1;
    build(i<<1,l,mid);build(i<<1|1,mid+1,r);
    tr[i]=tr[i<<1]+tr[i<<1|1];tr[i]%=mod;
}
void update(int i,int l,int r,int pl,int pr,int d){
    if(pl>=l and pr<=r ){
        addtag(i,pl,pr,d);
        return;
    }
    pushdown(i,pl,pr);
    int mid=(pl+pr)>>1;
    if(mid>=l) update(i<<1,l,r,pl,mid,d);
    if(mid<r) update(i<<1|1,l,r,mid+1,r,d);
    tr[i]=tr[i<<1]+tr[i<<1|1];tr[i]%=mod;
}
int query(int i,int l,int r,int pl,int pr){
    if(pl>=l and pr<=r) return tr[i];
    pushdown(i,pl,pr);
    int mid=(pl+pr)>>1;int res=0;
    if(mid>=l) res=query(i<<1,l,r,pl,mid);
    if(mid<r) res+=query(i<<1|1,l,r,mid+1,pr);
    res%=mod;
    return res;
}
void add(int u,int v){
    to[++cnt]=v,nxt[cnt]=head[u],head[u]=cnt;
}
int tot;
void dfs1(int x,int f){
    fa[x]=f,siz[x]=1,deep[x]=deep[f]+1;
    int num=0;
    for(int i=head[x];i;i=nxt[i]){
        int y=to[i];
        if(y!=f) dfs1(y,x);
        siz[x]+=siz[y];
        if(siz[y]>num){
            num=siz[y];
            son[x]=y;
        }
    }
}
void dfs2(int x,int topx){
    dfn[x]=++tot, newa[tot]=a[x];
    top[x]=topx;
    if(!son[x]) return;
    dfs2(son[x],topx);
    for(int i=head[x];i;i=nxt[i]){
        int y=to[i];
        if(y!=fa[x] and y!=son[x]) dfs2(y,y);
    }
}
void updline(int x,int y,int d){
    while(top[x]!=top[y]){
        if(deep[top[x]]<deep[top[y]]) swap(x,y);
        update(1,dfn[top[x]],dfn[x],1,n,d);
        x=fa[top[x]];
    }
    if(deep[x]>deep[y]) swap(x,y);
    update(1,dfn[x],dfn[y],1,n,d);
}
int qryline(int x,int y){
    int res=0;
    while(top[x]!=top[y]){
        if(deep[top[x]]<deep[top[y]]) swap(x,y);
        res+=query(1,dfn[top[x]],dfn[x],1,n);
        x=fa[top[x]];
        res%=mod;
    }
    if(deep[x]>deep[y]) swap(x,y);
    res+=query(1,dfn[x],dfn[y],1,n);res%=mod;
    return res;
}
void updtree(int x,int d){
    update(1,dfn[x],dfn[x]+dfn[x]+siz[x]-1,1,n,d);
}
int qrytree(int x){
    return query(1,dfn[x],dfn[x]+dfn[x]+siz[x]-1,1,n);
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin>>n>>m>>r>>mod;
    for(int i=1;i<=n;i++) cin>>a[i];
    for(int i=1;i<n;i++){
        int u,v;cin>>u>>v;
        add(u,v);add(v,u);
    }
    dfs1(r,0);dfs2(r,r);build(1,1,n);
    while(m--){
        int op;cin>>op;
        if(op==1){
            int x,y,d;cin>>x>>y>>d;
            updline(x,y,d);
        }
        if(op==2){
            int x,y;cin>>x>>y;
            cout<<qryline(x,y)<<'\n';
        }
        if(op==3){
            int x,d;cin>>x>>d;
            updtree(x,d);
        }
        if(op==4){
            int x;cin>>x;
            cout<<qrytree(x)<<'\n';
        }
    }
    return 0;
}

回复

11 条回复,欢迎继续交流。

正在加载回复...