本人思路线段树维护有理数区间赋值、区间求和,但是在写的时候莫名 RE,出了一些很奇怪的错误,比如 query 返回的结点信息突然全变成 0,查询的结果变成随机数。
第一次碰到这种错,真的不知道错哪了,求调qwq
#include <stdio.h>
#define int long long
#define lc (p<<(long long)1)
#define rc (p<<(long long)1|(long long)1)
#define mid ((l+r)>>(long long)1)
int gcd(int x,int y){
if(y==0) return x;
return gcd(y,x%y);
}
const int N=4e5+5;
struct tree{
int sfz,sfm; //区间和的分子和分母
int tfz,tfm; //懒标记
int op; //是否打了懒标记
void tag(int l,int r,int z,int m){
op=1;
tfz=z,tfm=m;
sfz=(r-l+1)*z;
sfm=m;
int d=gcd(sfz,sfm);
sfz/=d,sfm/=d;
}
}t[N*4];
int a[N],n,q;
void pushup(int p){
int d=gcd(t[lc].sfm,t[rc].sfm);
t[p].sfm=t[lc].sfm/d*t[rc].sfm;
t[p].sfz=t[lc].sfz/d*t[rc].sfm+t[rc].sfz/d*t[lc].sfm;
d=gcd(t[p].sfm,t[p].sfz);
t[p].sfm/=d;
t[p].sfz/=d;
}
void pushdown(int p,int l,int r){
if(t[p].op!=-1){
t[lc].tag(l,mid,t[p].tfz,t[p].tfm);
t[rc].tag(mid+1,r,t[p].tfz,t[p].tfm);
t[p].op=-1;
}
}
void build(int p,int l,int r){
// printf("%lld %lld %lld\n",p,l,r);
t[p].op=-1;
if(l==r){
t[p].sfz=a[l];
t[p].sfm=1;
return ;
}
build(lc,l,mid);
build(rc,mid+1,r);
pushup(p);
// printf("%lld %lld %lld %lld %lld\n",p,l,r,t[p].sfz,t[p].sfm);
}
void update(int p,int l,int r,int x,int y,int Fz,int Fm){
if(x<=l&&r<=y){
t[p].tag(l,r,Fz,Fm);
return ;
}
pushdown(p,l,r);
if(x<=mid) update(lc,l,mid,x,y,Fz,Fm);
if(y>mid) update(rc,mid+1,r,x,y,Fz,Fm);
pushup(p);
}
tree query(int p,int l,int r,int x,int y){
if(x<=l&&r<=y){
// printf("%lld %lld %lld %lld\n",l,r,t[p].sfz,t[p].sfm);
return t[p];
}
pushdown(p,l,r);
if(y<=mid) query(lc,l,mid,x,y);
else if(x>mid) query(rc,mid+1,r,x,y);
else{
tree t1=query(lc,l,mid,x,y),t2=query(rc,mid+1,r,x,y);
tree R;
int d=gcd(t1.sfm,t2.sfm);
// printf("%lld %lld %lld %lld %lld\n",p,t1.sfz,t1.sfm,t2.sfz,t2.sfm);
R.sfm=t1.sfm*t2.sfm;
R.sfz=t1.sfz*t2.sfm+t2.sfz*t1.sfm;
d=gcd(R.sfm,R.sfz);
// printf("%lld %lld %lld\n",R.sfz,R.sfm,d);
R.sfm/=d;
R.sfz/=d;
return R;
}
}
signed main(){
scanf("%lld%lld",&n,&q);
for(int i=1;i<=n;++i) scanf("%lld",&a[i]);
build(1,1,n);
while(q--){
int L,R; scanf("%lld%lld",&L,&R);
tree T=query(1,1,n,L,R);
// printf("%lld %lld\n",T.sfz,T.sfm);
T.sfm*=(R-L+1);
int d=gcd(T.sfm,T.sfz);
T.sfm/=d; T.sfz/=d;
update(1,1,n,L,R,T.sfz,T.sfm);
}
}