社区讨论
蒟蒻刚学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 条回复,欢迎继续交流。
正在加载回复...