社区讨论

19pts 2,4外TLE,悬两关

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

讨论操作

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

当前回复
9 条
当前快照
1 份
快照标识符
@mlgxvw3t
此快照首次捕获于
2026/02/11 02:33
上周
此快照最后确认于
2026/02/11 02:33
上周
查看原帖
CPP
#include<bits/stdc++.h>
#define endl '\n'
#define FastIO std::ios::sync_with_stdio(false);cin.tie(0);
using namespace std;
int n,m,r,p;
/*------------------------------------------------------*/
#define ls node<<1
#define rs node<<1|1
#define lb tr[node].l//左边界
#define rb tr[node].r//同理
#define tlt tr[node].lt//懒标记
#define tsum tr[node].sum//和 
struct Tree{
    int sum,l,r,lt;};
const int N=200005;
Tree tr[4*N];
void push_up(int node){tsum=tr[ls].sum+tr[rs].sum;tsum%=p;}
void push_down(int node){
	tr[ls].lt+=tlt;
    tr[ls].lt%=p;
	tr[rs].lt+=tlt;
    tr[rs].lt%=p;
    tr[ls].sum+=(tr[ls].r-tr[ls].l+1)*tlt;
    tr[ls].sum%=p;
	tr[rs].sum+=(tr[rs].r-tr[rs].l+1)*tlt;
    tr[rs].sum%=p;
	tlt=0;
}
void build(int node,int l,int r){
    lb=l,rb=r,tsum=tlt=0;
    if(l==r){
        tr[node]={0,l,r,0};
        return ;
    }
    int mid=(l+r)>>1;
    build(ls,l,mid);
    build(rs,mid+1,r);
    push_up(node);
}
void update(int node,int l,int r,int k){
    if(lb>=l&&rb<=r){
        tlt+=k;
        tsum+=(rb-lb+1)*k;
        tsum%=p;
        return ;
    }
    push_down(node);
    if(l<=((lb+rb)>>1)) update(ls,l,r,k);
    if(r>((lb+rb)>>1)) update(rs,l,r,k);
    push_up(node);
}
int query(int node,int l,int r){
    if(lb>=l&&rb<=r) 
        return tsum;    
    push_down(node);
    int res=0;
    if(l<=((lb+rb)>>1)) res+=query(ls,l,r);
    if(r>((lb+rb)>>1)) res+=query(rs,l,r);
    return res;
}
#undef ls 
#undef rs 
#undef lb 
#undef rb
#undef tlt
#undef tsum 
/*------------------------------------------------------*/
vector<int>g[N];
int val[N];
int dep[N];
int fa[N];
int siz[N];
int top[N];
int son[N];//重儿子
int id[N];
int rk[N];
int len=0;
void dfs1(int u,int pre){
    dep[u]=dep[pre]+1;
    fa[u]=pre;
    siz[u]=1;
    int ma=0;
    for(int v:g[u]){
        if(v==pre) continue;
        dfs1(v,u);
        siz[u]+=siz[v];
        if(siz[v]>ma){
            ma=siz[v];
            son[u]=v;
        }
    }
}
void dfs2(int u,int ttop){
    top[u]=ttop;
    id[u]=++len;
    rk[len]=u;
    if(son[u]){
        dfs2(son[u],ttop);
        for(auto v:g[u]){
            if(v==fa[u]||v==son[u]) continue;
            dfs2(v,v);
        }
    }
}
void update1(int x,int y,int k){//链上
    while(top[x]!=top[y]){
        if(dep[top[x]]<dep[top[y]]) swap(x,y);
        update(1,id[top[x]],id[x],k);
        x=fa[top[x]];
    }
    if(dep[x]>dep[y]) swap(x,y);
    update(1,id[x],id[y],k);
}
int query1(int x,int y){//链上
    int res=0;
    while(top[x]!=top[y]){
        if(dep[top[x]]<dep[top[y]]) swap(x,y);
        res+=query(1,id[top[x]],id[x]);
        x=fa[top[x]];
    }
    if(dep[x]>dep[y]) swap(x,y);
    res+=query(1,id[x],id[y]);
    return res;
}
void update2(int x,int k){//子树
    update(1,id[x],id[x]+siz[x]-1,k);
}
int query2(int x){//子树
    return query(1,id[x],id[x]+siz[x]-1);
}
signed main(){
    FastIO
    cin>>n>>m>>r>>p;
    build(1,1,n);
    for(int i=1;i<=n;i++){
        cin>>val[i];
    }
    for(int i=1;i<n;i++){
        int x,y;
        cin>>x>>y;
        g[x].push_back(y);
        g[y].push_back(x);
    }
    dfs1(r,0);
    dfs2(r,1);
    for(int i=1;i<=n;i++){
        update(1,id[i],id[i],val[i]);
    }
    while(m--){
        int op,x,y,z;
        cin>>op>>x;
        if(op==1){
            cin>>y>>z;
            update1(x,y,z%p);
        }else if(op==2){
            cin>>y;
            cout<<query1(x,y)%p<<endl;
        }else if(op==3){
            cin>>z;
            update2(x,z%p);
        }else{
            cout<<query2(x)%p<<endl;
        }
    }
}

回复

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

正在加载回复...