社区讨论
蒟蒻求助
P3384【模板】重链剖分 / 树链剖分参与者 2已保存回复 2
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 2 条
- 当前快照
- 1 份
- 快照标识符
- @mi85w0j1
- 此快照首次捕获于
- 2025/11/21 09:08 4 个月前
- 此快照最后确认于
- 2025/11/21 09:08 4 个月前
树剖板子
CPP#include<bits/stdc++.h>
using namespace std;
#define mod p
struct Edge
{
int fr,to;
}eg[400005];
int head[100005],edgenum;
struct SegNode
{
int l,r,val,lazy;
}sn[800005];
struct TreeNode
{
int fa,deep,son,id,top,size,val;
}tn[400005];
int firstw[100005],n,m,r,p;
inline void add(int fr,int to)
{
eg[++edgenum].fr=head[fr];
eg[edgenum].to=to;
head[fr]=edgenum;
}
#define len(x) sn[x].r-sn[x].l+1
inline void pushup(int rt)
{
sn[rt].val=sn[rt<<1].val+sn[rt<<1|1].val;
sn[rt].val%=mod;
}
inline void pushdown(int rt,int len)
{
if(sn[rt].lazy)
{
sn[rt<<1].lazy+=sn[rt].lazy;
sn[rt<<1|1].lazy+=sn[rt].lazy;
sn[rt<<1].val+=sn[rt].lazy*(len-(len>>1));
sn[rt<<1|1].val+=sn[rt].lazy*(len>>1);
sn[rt<<1].val%=mod;
sn[rt<<1|1].val%=mod;
sn[rt].lazy=0;
}
}
inline int query(int rt,int l,int r,int fr,int to)
{
int ans=0;
if(fr<=l&&to>=r)
{
ans=sn[rt].val;
return ans%mod;
}
pushdown(rt,r-l+1);
int mid=(l+r)>>1;
if(fr<=mid) ans+=query(rt<<1,l,mid,fr,to);
if(to>mid) ans+=query(rt<<1|1,mid+1,r,fr,to);
return ans%mod;
}
inline void update(int rt,int l,int r,int fr,int to,int val)
{
if(fr<=l&&to>=r)
{
sn[rt].lazy+=val;
sn[rt].val+=val*(r-l+1);
return;
}
pushdown(rt,r-l+1);
int mid=(l+r)>>1;
if(fr<=mid) update(rt<<1,l,mid,fr,to,val);
if(to>mid) update(rt<<1|1,mid+1,r,fr,to,val);
pushup(rt);
}
inline void build(int rt,int l,int r)
{
if(l>r) return;
sn[rt].l=l;
sn[rt].r=r;
sn[rt].lazy=0;
if(l==r)
{
sn[rt].val=tn[l].val;
sn[rt].val%=mod;
return;
}
int mid=(l+r)>>1;
build(rt<<1,l,mid);
build(rt<<1|1,mid+1,r);
pushup(rt);
}
int cnt;
inline void dfs1(int x,int fa,int deep)
{
tn[x].deep=deep;
tn[x].fa=fa;
tn[x].size=1;
int maxson=-1;
for(int i=head[x];i;i=eg[i].fr)
{
if(eg[i].to==fa) continue;
dfs1(eg[i].to,x,deep+1);
tn[x].size+=tn[eg[i].to].size;
if(tn[eg[i].to].size>maxson)
maxson=tn[eg[i].to].size,tn[x].son=eg[i].to;
}
}
inline void dfs2(int x,int top)
{
tn[x].id=++cnt;
tn[x].top=top;
tn[cnt].val=firstw[x];
if(!tn[x].son) return;
dfs2(tn[x].son,top);
for(int i=head[x];i;i=eg[i].fr)
{
if(eg[i].to==tn[x].fa||eg[i].to==tn[x].son)
continue;
dfs2(eg[i].to,eg[i].to);
}
}
inline void updateroad(int x,int y,int val)
{
val%=mod;
while(tn[x].top!=tn[y].top)
{
if(tn[tn[x].top].deep<tn[tn[y].top].deep) swap(x,y);
update(1,1,n,tn[tn[x].top].id,tn[x].id,val);
x=tn[tn[x].top].fa;
}
if(tn[x].deep>tn[y].deep) swap(x,y);
update(1,1,n,tn[x].id,tn[y].id,val);
}
inline int queryroad(int x,int y)
{
int ans=0;
while(tn[x].top!=tn[y].top)
{
if(tn[tn[x].top].deep<tn[tn[y].top].deep) swap(x,y);
ans+=query(1,1,n,tn[tn[x].top].id,tn[x].id);
ans%=mod;
x=tn[tn[x].top].fa;
}
if(tn[x].deep>tn[y].deep) swap(x,y);
ans+=query(1,1,n,tn[x].id,tn[y].id);
ans%=mod;
return ans;
}
inline int querytree(int rt)
{
return query(1,1,n,tn[rt].id,tn[rt].id+tn[rt].size-1);
}
inline void updatetree(int rt,int k)
{
update(1,1,n,tn[rt].id,tn[rt].id+tn[rt].size-1,k);
}
int main()
{
scanf("%d%d%d%d",&n,&m,&r,&p);
for(int i=1;i<=n;++i)
scanf("%d",&firstw[i]);
int a,b;
for(int i=1;i<n;++i)
{
scanf("%d%d",&a,&b);
add(a,b);
add(b,a);
}
dfs1(r,0,1);
dfs2(r,r);
build(1,1,n);
int op,c;
for(int i=1;i<=m;++i)
{
scanf("%d",&op);
if(op==1)
{
scanf("%d%d%d",&a,&b,&c);
updateroad(a,b,c);
}
if(op==2)
{
scanf("%d%d",&a,&b);
printf("%d\n",queryroad(a,b));
}
if(op==3)
{
scanf("%d%d",&a,&b);
updatetree(a,b);
}
if(op==4)
{
scanf("%d",&a);
printf("%d\n",querytree(a));
}
}
return 0;
}
重点是为什么pushdown为什么一定要用一个r-l+1
我一开始写的是用s[rt].r-s[rt].l+1
然后就调了一个下午
回复
共 2 条回复,欢迎继续交流。
正在加载回复...