社区讨论
树剖,但是连样例都输不进去
P3384【模板】重链剖分 / 树链剖分参与者 3已保存回复 13
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 13 条
- 当前快照
- 1 份
- 快照标识符
- @lo8hvpdl
- 此快照首次捕获于
- 2023/10/27 18:53 2 年前
- 此快照最后确认于
- 2023/10/27 18:53 2 年前
CPP
#include<stdio.h>
#include<vector>
using namespace std;
int n,m,r,p;
int dfn[200086],rfn[200086],fa[200086],siz[200086],top[200086],hevs[200086],dep[200086];
vector<int>e[200086];
int temp;
struct node{
int l,r;
long long val,lzd;
}te[8000086];
int a[100086];
void t_build(int l,int r,int now)
{
te[now].l=l;
te[now].r=r;
te[now].val=te[now].lzd=0;
if(l!=r)
{
int mid=(l+r)/2;
t_build(l,mid,now*2);
t_build(mid+1,r,now*2+1);
te[now].val=te[now*2].val+te[now*2+1].val;
}
else te[now].val=a[dfn[l]];
te[now].val%=p;
}
inline void lzd_down(int now)
{
if(te[now].lzd)
{
te[now*2].val+=te[now].lzd*(te[now*2].r-te[now*2].l+1);
te[now<<1].val%=p;
te[now*2+1].val+=te[now].lzd*(te[now*2+1].r-te[now*2+1].l+1);
te[(now<<1)|1].val%=p;
te[now*2].lzd+=te[now].lzd;
te[now<<1].lzd%=p;
te[now*2+1].lzd+=te[now].lzd;
te[(now<<1)|1].lzd%=p;
te[now].lzd=0;
}
}
void add(int now,int l,int r,long long val)
{
if(l<=te[now].l&&r>=te[now].r)
{
te[now].lzd+=val;
te[now].lzd%=p;
te[now].val+=(te[now].r-te[now].l+1)*val;
te[now].val%=p;
return;
}
int mid=(te[now].l+te[now].r)/2;
lzd_down(now);
if(l<=mid)
add(now*2,l,r,val);
if(mid+1<=r)
add(now*2+1,l,r,val);
te[now].val=te[now*2].val+te[now*2+1].val;
te[now].val%=p;
}
long long search(int l,int r,int now)
{
if(l<=te[now].l&&r>=te[now].r)
return te[now].val;
int mid=(te[now].l+te[now].r)/2;
long long ans=0;
lzd_down(now);
if(l<=mid)
ans+=search(l,r,now*2),ans%=p;
if(mid+1<=r)
ans+=search(l,r,now*2+1),ans%=p;
return ans;
}
//线段树板子
void dfs1(int now,int f,int deep)
{
siz[now]=1;
fa[now]=f;
dep[now]=deep;
for(int i=0;i<e[now].size();i++)
{
int oth=e[now][i];
if(oth!=f)
{
dfs1(oth,now,deep+1);
siz[now]+=siz[oth];
if(siz[oth]>siz[hevs[now]])
hevs[now]=oth;
}
}
}
void dfs2(int now,int f)
{
if(hevs[now])
{
dfn[hevs[now]]=++temp;
top[hevs[now]]=top[now];
rfn[temp]=hevs[now];
dfs2(hevs[now],now);
}
for(int i=0;i<e[now].size();i++)
{
int oth=e[now][i];
if(!top[oth])
{
dfn[oth]=++temp;
rfn[temp]=oth;
top[oth]=oth;
dfs2(oth,now);
}
}
}
//树剖
int main()
{
scanf("%d%d%d%d",&n,&m,&r,&p);
for(int i=1;i<=n;i++)
scanf("%d",a+i);
for(int i=1;i<n;i++)
{
int a,b;
scanf("%d%d",&a,&b);
e[a].push_back(b);
e[b].push_back(a);
}
dfn[r]=temp=1;
rfn[1]=r;
top[r]=r;
dfs1(r,0,1);
dfs2(r,0);
t_build(1,n,1);
/*for(int i=1;i<=n;i++)
{
printf("%d:",dfn[i]);
for(int j=0;j<e[i].size();j++)
printf("%d ",e[i][j]);
printf(" %d",hevs[i]);
printf("\n");
}*/
while(m--)
{
int op,x,y;
long long z;
scanf("%d",&op);
if(op==1)
{
scanf("%d%d%lld",&x,&y,&z);
z%=p;
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]])
x^=y,y^=x,x^=y;
add(1,dfn[top[x]],dfn[x],z);
x=fa[top[x]];
}
if(dep[x]>dep[y])
x^=y,y^=x,x^=y;
add(1,dfn[x],dfn[y],z);
}
else if(op==2)
{
long long ans=0;
scanf("%d%d",&x,&y);
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]])
x^=y,y^=x,x^=y;
ans+=search(1,dfn[top[x]],dfn[x]);
ans%=p;
x=fa[top[x]];
}
if(dep[x]>dep[y])
x^=y,y^=x,x^=y;
ans+=search(1,dfn[x],dfn[y]);
ans%=p;
printf("%lld\n",ans);
}
else if(op==3)
{
scanf("%d%lld",&x,&z);
z%=p;
add(1,dfn[x],dfn[x]+siz[x]-1,z);
}
else
{
scanf("%d",&x);
printf("%lld\n",search(1,dfn[x],dfn[x]+siz[x]-1));
}
}
return 0;
}
样例:
5 5 2 24
7 3 7 8 0
1 2
1 5
3 1
4 1
3 4 2
3 2 2
4 5
1 5 1 3
2 1 3
输到"4 5"时就会卡炸掉,估计是建树或者是search的问题,但具体怎么回事就不知道了
救救孩子吧!
回复
共 13 条回复,欢迎继续交流。
正在加载回复...