hamster000 @ 2024-02-16 22:48:26
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
int mod,dep[maxn],dfn[maxn],rnk[maxn],siz[maxn],fa[maxn],top[maxn],son[maxn];
int w[maxn],wt[maxn];
vector <int> vec[maxn];
void dfs(int u,int f){
siz[u]=1;fa[u]=f,dep[u]=dep[f]+1;
for(auto to:vec[u]){
if(to==f) continue;
dfs(to,u);
siz[u]+=siz[to];
if(siz[to]>siz[son[u]]){
son[u]=to;
}
}
}
int cnt=0;
void dfs2(int u,int tp){
top[u]=tp,dfn[u]=++cnt,rnk[cnt]=u;
wt[cnt]=w[u];
if(!son[u]) return ;
dfs2(son[u],tp);
for(auto to:vec[u]){
if(to==fa[u]||to==son[u]) continue;
dfs2(to,to);
}
}
#define lc 2*rt
#define rc 2*rt+1
int val[4*maxn],lazy[4*maxn],le[maxn*4],ri[maxn*4];
void pushup(int rt){
val[rt]=(val[lc]+val[rc])%mod;
return ;
}
void pushdown(int rt){
if(!lazy[rt]) return ;
lazy[lc]+=lazy[rt];
lazy[rc]+=lazy[rt];
val[lc]+=lazy[rt]*(ri[lc]-le[lc]+1);
val[rc]+=lazy[rt]*(ri[rc]-le[rc]+1);
lazy[rt]=0;
}
void build(int rt,int l,int r){
le[rt]=l,ri[rt]=r;
if(l==r){
val[rt]=wt[l];
}else{
int mid=(l+r) >> 1;
build(lc,l,mid);
build(rc,mid+1,r);
pushup(rt);
}
}
long long res;
void query_sum(int rt,int x,int y){
int l=le[rt],r=ri[rt];
if(x<=l&&r<=y){
res+=val[rt];
res%=mod;
return ;
}
int mid=(l+r)/2;
pushdown(rt);
if(x<=mid){
query_sum(lc,x,y);
}if(y>mid){
query_sum(rc,x,y);
}
}
//x,y:修改区间
void update(int rt,int x,int y,int k){
int l=le[rt],r=ri[rt];
if(x<=l&&r<=y){
val[rt]+=k*(r-l+1);
lazy[rt]+=k;
}else{
pushdown(rt);
int mid=(l+r)/2;
if(x<=mid) update(lc,x,y,k);
if(r>mid) update(rc,x,y,k);
pushup(rt);
}
}
int query_Range(int x,int y){
int ans=0;
while(top[x]!=top[y]){
if(dep[top[x]]!=dep[top[y]]) swap(x,y);
res=0;
query_sum(1,dfn[top[x]],dfn[x]);
ans+=res;
ans%=mod;
x=fa[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
res=0;
query_sum(1,dfn[x],dfn[y]);
ans+=res;
return ans%mod;
}
int querySon(int rt){
res=0;
query_sum(1,dfn[rt],dfn[rt]+siz[rt]-1);
return res;
}
void updateRange(int x,int y,int k){
k%=mod;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
update(1,dfn[top[x]],dfn[x],k);
x=fa[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
update(1,dfn[x],dfn[y],k);
}
void updateSon(int x,int k){
update(1,dfn[x],dfn[x]+siz[x]-1,k);
}
int main(){
int n,m,r,p;
cin >> n >> m >> r >> p;
mod=p;
for(int i=1;i<=n;i++){
cin >> w[i];
}
for(int i=1;i<n;i++){
int a,b;
cin >> a >> b;
vec[a].push_back(b);
vec[b].push_back(a);
}
dfs(r,0);
dfs2(r,r);
build(1,1,n);
while(m--){
int opt,x,y,z;
cin >> opt;
if(opt==1){
cin >> x >> y >> z;
updateRange(x,y,z);
}if(opt==2){
cin >> x >> y;
cout << query_Range(x,y) << endl;
}if(opt==3){
cin >> x >> z;
updateSon(x,z);
}if(opt==4){
cin >> x;
cout << querySon(x) << endl;
}
}
}
样例都没过,请大佬帮忙找找问题。
by hamster000 @ 2024-02-16 22:58:47
抱歉耽误各位时间。问题已经解决。 问题出在代码81行
if(r>mid) update(rc,x,y,k);
应为
if(y>mid) update(rc,x,y,k);
总结:线段树出现错误,没有搞清楚什么是需要update的东西。警钟长鸣。
修改之后可以通过三个点,仍然有一定问题,请各位指出。
by 142857tree @ 2024-02-16 23:06:33
query_range 第三行
by hamster000 @ 2024-02-16 23:07:16
成功定位问题在第86行 query_Range函数(计算一条链上的和)。 错误发现在89行。
if(dep[top[x]]!=dep[top[y]]) swap(x,y);
应为
if(dep[top[x]]<dep[top[y]]) swap(x,y);
原因:一条链上的答案之和可以被多次跳重链到它们的
提交之后能够得到满分