Dino_chx @ 2023-08-13 10:31:32
这个是跟着日报学的树剖,但是不知道为什么过不了样例,求助qwq
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e5+7;
vector<int> e[N];
int n,m,root,P,a[N],fa[N],d[N],siz[N],son[N],rk[N],top[N],dfn[N],thistime;
struct Segment_Tree
{
struct maintain
{
int l,r;
ll sum,tag;
}tree[N<<2];
void pushup(int x)
{
tree[x].sum=(tree[x<<1].sum+tree[x<<1|1].sum)%P;
return;
}
void build(int x,int l,int r)
{
tree[x]={l,r};
if(l==r)
{
tree[x].sum=a[rk[l]]%P;
return;
}
int mid=l+r>>1;
build(x<<1,l,mid);
build(x<<1|1,mid+1,r);
pushup(x);
return;
}
void pushdown(int x)
{
maintain &rt=tree[x],&ls=tree[x<<1],&rs=tree[x<<1|1];
if(rt.tag)
{
ls.tag=(ls.tag+rt.tag)%P;
rs.tag=(rs.tag+rt.tag)%P;
ls.sum=(ls.sum+(ls.r-ls.l+1)*rt.tag%P)%P;
rs.sum=(ls.sum+(rs.r-rs.l+1)*rt.tag%P)%P;
rt.tag=0;
}
return;
}
void update(int x,int l,int r,int k)
{
if(l<=tree[x].l&&r>=tree[x].r)
{
tree[x].sum=(tree[x].sum+(tree[x].r-tree[x].l+1)*k%P)%P;
tree[x].tag=(tree[x].tag+k)%P;
return;
}
pushdown(x);
int mid=tree[x].l+tree[x].r>>1;
if(l<=mid)
update(x<<1,l,r,k);
if(r>mid)
update(x<<1|1,l,r,k);
pushup(x);
return;
}
ll query(int x,int l,int r)
{
if(l<=tree[x].l&&r>=tree[x].r)
return tree[x].sum%P;
pushdown(x);
int mid=tree[x].l+tree[x].r>>1;
ll res=0;
if(l<=mid)
res=(res+query(x<<1,l,r))%P;
if(r>mid)
res=(res+query(x<<1|1,l,r))%P;
return res%P;
}
}tree;
void dfs1(int x,int Fa)
{
fa[x]=Fa;
siz[x]=1;
d[x]=d[Fa]+1;
for(auto it:e[x])
{
if(it!=Fa)
{
dfs1(it,x);
siz[x]+=siz[it];
if(siz[it]>siz[son[x]])
son[x]=it;
}
}
return;
}
void dfs2(int x,int tp)
{
top[x]=tp;
dfn[x]=++thistime;
rk[thistime]=x;
if(!son[x])
return;
dfs2(son[x],tp);
for(auto it:e[x])
{
if(it!=son[x]&&it!=fa[x])
dfs2(it,it);
}
return;
}
ll query_edge(int x,int y)
{
int fx=top[x],fy=top[y];
ll res=0;
while(fx!=fy)
{
if(d[fx]>=d[fy])
{
res=(res+tree.query(1,dfn[fx],dfn[x]))%P;
x=fa[fx];
fx=top[x];
}
else
{
res=(res+tree.query(1,dfn[fy],dfn[y]))%P;
y=fa[fy];
fy=top[y];
}
}
if(dfn[x]<=dfn[y])
res=(res+tree.query(1,dfn[x],dfn[y]))%P;
else
res=(res+tree.query(1,dfn[y],dfn[x]))%P;
return res%P;
}
void update_edge(int x,int y,int c)
{
int fx=top[x],fy=top[y];
while(fx!=fy)
{
if(d[fx]>=d[fy])
{
tree.update(1,dfn[fx],dfn[x],c);
x=fa[fx];
fx=top[x];
}
else
{
tree.update(1,dfn[fy],dfn[y],c);
y=fa[fy];
fy=top[y];
}
}
if(dfn[x]<=dfn[y])
tree.update(1,dfn[x],dfn[y],c);
else
tree.update(1,dfn[y],dfn[x],c);
return;
}
int main()
{
scanf("%d%d%d%d",&n,&m,&root,&P);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
for(int i=1,u,v;i<n;i++)
{
scanf("%d%d",&u,&v);
e[u].push_back(v);
e[v].push_back(u);
}
d[root]=1;
dfs1(root,0);
dfs2(root,root);
tree.build(1,1,n);
while(m--)
{
int op,x,y,z;
scanf("%d",&op);
if(op==1)
{
scanf("%d%d%d",&x,&y,&z);
update_edge(x,y,z);
}
if(op==2)
{
scanf("%d%d",&x,&y);
printf("%lld\n",query_edge(x,y));
}
if(op==3)
{
scanf("%d%d",&x,&z);
tree.update(1,dfn[x],dfn[x]+siz[x]-1,z);
}
if(op==4)
{
scanf("%d",&x);
printf("%lld\n",tree.query(1,dfn[x],dfn[x]+siz[x]-1));
}
}
return 0;
}
by ax_by_c @ 2023-08-13 10:34:15
这边建议花个半小时重新打一遍
其实是死因和我不一样
by liuxy1234 @ 2023-08-13 10:37:06
可以把树剖和线段树拆开调试试试
by ax_by_c @ 2023-08-13 11:07:01
调完了
死因:第41行的rs打成了ls
by ax_by_c @ 2023-08-13 11:07:28
哈哈哈线段树寄了
by ax_by_c @ 2023-08-13 11:07:48
啸死我了
by Dino_chx @ 2023-08-14 08:08:25
过了,谢谢
by yanjiadong @ 2024-08-25 10:18:54
啸死了时隔多年我没调用dfs1dfs2build