社区讨论

蒟蒻刚学OI。本地过了下载样例,提交RE 0分。

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

讨论操作

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

当前回复
27 条
当前快照
1 份
快照标识符
@mi86iza5
此快照首次捕获于
2025/11/21 09:26
4 个月前
此快照最后确认于
2025/11/21 10:01
4 个月前
查看原帖
RT
CPP
#include<bits/stdc++.h>
#define int long long
#define L u*2
#define R u*2+1
#define mid (l+r)/2
using namespace std;
int n,m,rt,MOD;
struct A{
    int fa,dep,son,rec,siz,val;
}po[200005];
int top[200005],reccnt;
struct B{
    int t,nxt;
}ed[200005];
int head[200005],cnt;
int val[200005];
///////////////////////////////////////////////////////////////////////////////////////////////
int a[200005];
struct xds{
    int v,tag;
}p[400005];
int build(int u,int l,int r){
    if(l==r)
        return p[u].v=val[l];
    return p[u].v=build(L,l,mid)+build(R,mid+1,r);
}
void update(int u){
    p[u].v=p[L].v+p[R].v;
}
void push_down(int u,int l,int r){
    p[L].v=(p[L].v+p[u].tag*(mid-l+1))%MOD;
    p[R].v=(p[R].v+p[u].tag*(r-mid))%MOD;
    p[L].tag=(p[L].tag+p[u].tag)%MOD;
    p[R].tag=(p[R].tag+p[u].tag)%MOD;
    p[u].tag=0;
}
void insert(int u,int l,int r,int x,int y,int k){
    if(l==x&&y==r){
        p[u].tag=(p[u].tag+k)%MOD,p[u].v=(p[u].v+k*(r-l+1))%MOD;
        return;
    }
    push_down(u,l,r);
    if(y<=mid)
        insert(L,l,mid,x,y,k);
    else if(x>=mid+1)
        insert(R,mid+1,r,x,y,k);
    else{
        insert(L,l,mid,x,mid,k);
        insert(R,mid+1,r,mid+1,y,k);
    }
    update(u);
    return;
}
int query(int u,int l,int r,int x,int y){
    int ans=0;
    if(l==x&&y==r)
        return p[u].v;
    push_down(u,l,r);
    if(y<=mid)
        ans=query(L,l,mid,x,y)%MOD;
    else if(x>=mid+1)
        ans=query(R,mid+1,r,x,y)%MOD;
    else
        ans=(query(L,l,mid,x,mid)%MOD+query(R,mid+1,r,mid+1,y)%MOD)%MOD;
    update(u);
    return ans;
}
///////////////////////////////////////////////////////////////////////////////////////////////

void add(int a,int b){
    ed[++cnt].t=b;
    ed[cnt].nxt=head[a];
    head[a]=cnt;
}
int dfs1(int u,int fa){
    int max=0,h_son;
    po[u].fa=fa;
    po[u].dep=po[po[u].fa].dep+1;
    po[u].siz=1;
    for(int i=head[u];i;i=ed[i].nxt){
        int x=ed[i].t,ssiz=0;
        if(!po[x].dep){
            ssiz=dfs1(x,u);
            if(ssiz>max)
                max=ssiz,h_son=x;
            po[u].siz+=ssiz;
        }
    }
    po[u].son=h_son;
    return po[u].siz;
}
void dfs2(int u,int tp){
    top[u]=tp;
    po[u].rec=++reccnt;
    if(po[u].son&&!po[po[u].son].rec)
        dfs2(po[u].son,tp); 
    for(int i=head[u];i;i=ed[i].nxt){
        int x=ed[i].t;
        if(!(po[x].rec))
            dfs2(x,x);
    }
}
signed main(){
    cin>>n>>m>>rt>>MOD;
    for(int i=1;i<=n;++i)
        scanf("%lld",&po[i].val);
    for(int i=1,x,y;i<=n-1;++i){
        scanf("%lld %lld",&x,&y);
        add(x,y);
        add(y,x);
    }
    po[rt].fa=-1,po[rt].dep=1;
    dfs1(rt,0);
    dfs2(rt,rt);
    for(int i=1;i<=n;++i){
    	val[po[i].rec]=po[i].val;
	}
    build(1,1,n);
    for(int i=1,cmd,x,y,z;i<=m;++i){
        scanf("%lld",&cmd);
        if(cmd==1){
            scanf("%lld %lld %lld",&x,&y,&z);//从x->y的最短路径上所有元素+=z
            z%=MOD;
            int fx=top[x],fy=top[y];
            while(fx!=fy){
            	if(po[fx].dep<po[fy].dep)
            		swap(x,y),swap(fx,fy);
            	insert(1,1,n,po[fx].rec,po[x].rec,z);
            	x=po[fx].fa,fx=top[x];
			}
			if(po[x].dep>po[y].dep)
				swap(x,y);
            insert(1,1,n,po[x].rec,po[y].rec,z);
        }
        if(cmd==2){
            scanf("%lld %lld",&x,&y);//求从x->y的最短路径上所有元素的和 
            int fx=top[x],fy=top[y],ans=0;
            while(fx!=fy){
            	if(po[fx].dep<po[fy].dep)
            		swap(x,y),swap(fx,fy);
            	ans=(ans+query(1,1,n,po[fx].rec,po[x].rec))%MOD;
            	x=po[fx].fa,fx=top[x];
			}
			if(po[x].dep>po[y].dep)
				swap(x,y);
            ans=(ans+query(1,1,n,po[x].rec,po[y].rec))%MOD;
            printf("%lld\n",ans%MOD);
        }
        if(cmd==3){
            scanf("%lld %lld",&x,&z);//以x为根的子树中所有元素+=z
            z%=MOD;
            insert(1,1,n,po[x].rec,po[x].rec+po[x].siz-1,z);
        }
        if(cmd==4){
            scanf("%lld",&x);//求以x为根的子树中所有元素的和 
            printf("%lld\n",query(1,1,n,po[x].rec,po[x].rec+po[x].siz-1)%MOD);
        }
    }
    return 0;
} 

回复

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

正在加载回复...