zhfaz123 @ 2023-03-30 13:40:27
代码:
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<stack>
#include<iostream>
#include<vector>
#define N (int(1e5))
using namespace std;
int son[N+1],id[N+1],sz[N+1],fa[N+1],dep[N+1],dfc,top[N+1],w[N+1],nw[N+1];//树的变量
int n,m,p,q;
vector<int> edge[N+1];//图
struct g
{
int l,r;
long long lazy,data;
g():l(0),r(0),lazy(0),data(0){};
}a[((N)<<2)+1];//线段树
//线段树
void build(int root,int l,int r)
{
a[root].l=l;
a[root].r=r;
int mid=l+r>>1;
if(l==r)
{
a[root].data=nw[l]%p;
return ;
}
build(root<<1,l,mid);
build(root<<1|1,mid+1,r);
a[root].data=a[root<<1].data+a[root<<1|1].data;
}
inline void push_down(int root)
{
if(a[root].lazy)
{
int mid=a[root].l+a[root].r>>1;
a[root<<1].lazy+=a[root].lazy;
a[root<<1|1].lazy+=a[root].lazy;
a[root<<1].data+=(a[root<<1].r-a[root<<1].l+1)*a[root].lazy;
a[root<<1|1].data+=(a[root<<1|1].r-a[root<<1|1].l+1)*a[root].lazy;
a[root].lazy=0;
}
}
void add(int root,int l,int r,long long k)
{
int mid=a[root].l+a[root].r>>1;
if(l <= a[root].l && r >=a[root].r)
{
a[root].data=(a[root].data%p+k%p)%p;
a[root].lazy=(a[root].lazy%p+k%p)%p;
return;
}
push_down(root);
if(l<=mid)add(root<<1,l,r,k);
if(r>mid)add(root<<1|1,l,r,k);
a[root].data=a[root<<1].data+a[root<<1|1].data;
return ;
}
int query(int root,int l,int r)
{
int mid=a[root].l+a[root].r>>1;
long long ret=0;
if(l <= a[root].l && r >=a[root].r)
{
return a[root].data%p;
}
push_down(root);
if(l<=mid)ret=(ret%p+query(root<<1,l,r)%p)%p;
if(r>mid)ret=(ret%p+query(root<<1|1,l,r)%p)%p;
a[root].data=a[root<<1].data+a[root<<1|1].data;
return ret;
}
//线段树结束
void dfs(int root,int f,int deep)
{
fa[root]=f;
sz[root]=1;
dep[root]=deep;
int hvs=-1;
for(auto &i:edge[root])
{
if(i==f)
continue;
dfs(i,root,deep+1);
sz[root]+=sz[i];
if(sz[i]>hvs)
{
hvs=sz[i];
son[root]=i;
}
}
}//第一遍dfs
void dfs2(int root,int topf)
{
id[root]=++dfc;
nw[id[root]]=w[root];
top[root]=topf;
if(!son[root])
return;
dfs2(son[root],topf);
for(auto &i:edge[root])
{
if(i == son[root] || i == fa[root])
continue;
dfs2(i,i);
}
}//第二遍dfs
void addpath(int x,int y,long long k)
{
while(top[x] != top[y])
{
if(dep[top[x]]<dep[top[y]])
swap(x,y);
add(1,id[top[x]],id[x],k%p);
x=fa[top[x]];
}
if(dep[x]<dep[y])
swap(x,y);
add(1,id[y],id[x],k%p);
return ;
}//增加路径和
long long querypath(int x,int y)
{
long long ret=0;
while(top[x] != top[y])
{
if(dep[top[x]]<dep[top[y]])
swap(x,y);
ret=(ret%p+query(1,id[top[x]],id[x])%p)%p;
x=fa[top[x]];
}
if(dep[x]<dep[y])
{
swap(x,y);
}
ret=(ret%p+query(1,id[y],id[x])%p)%p;
return ret;
}//查询路径和
void addtree(int x,long long k)
{
add(1,id[x],id[x]+sz[x]-1,k);
}//增加子树和
long long querytree(int x)
{
long long ret=0;
ret=(ret%p+query(1,id[x],id[x]+sz[x]-1)%p)%p;
return ret;
}//查询子树和
int main()
{
scanf("%d %d %d %d",&n,&q,&m,&p);
for(int i=1;i<=n;i++)
{
scanf("%d",&w[i]);
}
for(int i=1;i<=n-1;i++)
{
int x,y;
scanf("%d %d",&x,&y);
edge[x].push_back(y);
edge[y].push_back(x);
}
dfs(m,0,1);
dfs2(m,m);
build(1,1,n);//建树
for(int i=1;i<=q;i++)
{
int op;
scanf("%d",&op);
switch (op)
{
case 1:
{
int x,y;
long long k;
scanf("%d %d %lld",&x,&y,&k);
addpath(x,y,k);
break;
}
case 2:
{
int x,y;
scanf("%d %d",&x,&y);
printf("%lld\n",querypath(x,y)%p);
break;
}
case 3:
{
int x;
long long k;
scanf("%d %lld",&x,&k);
addtree(x,k);
break;
}
case 4:
{
int x;
scanf("%d",&x);
printf("%lld\n",querytree(x)%p);
break;
}
default:
break;
}
}
return 0;
}
by puck @ 2023-03-30 14:50:34
别的不说,首先你所有的mid就有位运算优先级问题吧
by zhfaz123 @ 2023-03-30 15:48:09
@puck 没错啊。 a+b>>1不是等于(a+b)>>1吗?
by puck @ 2023-03-30 16:16:58
@zhfaz123 优先级记反了XD,好像是add那里应该要加k*区间长度,你加的k
by zhfaz123 @ 2023-03-30 16:36:05
@puck 谢谢,改了之后就AC了