随了一百组 n=q=105,opt=3 的数据都过了,但是 opt=3 的随机数据总是差一点。
蒟蒻认为这份代码有可能错在操作三的区间覆盖,但是并没有查出任何错误。
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+3;
int n,m;
double a[maxn],b[maxn];
namespace Segtree{
#define ls (pos<<1)
#define rs (pos<<1|1)
struct Seg{
int l,r;
double x,y,xx,xy;
double s,t;
int cov;
}tr[maxn<<2];
#define mid ((tr[pos].l+tr[pos].r)>>1)
void push_u(int pos){
tr[pos].x=tr[ls].x+tr[rs].x;
tr[pos].y=tr[ls].y+tr[rs].y;
tr[pos].xx=tr[ls].xx+tr[rs].xx;
tr[pos].xy=tr[ls].xy+tr[rs].xy;
}
double sum(double x){
return x*(x+1)*(2*x+1)/6.0;
}
double sum(int l,int r){
return sum(r)-sum(l-1);
}
void push_d(int pos){
if(tr[pos].cov){
tr[ls].cov=tr[rs].cov=1;
tr[ls].s=tr[ls].t=tr[rs].s=tr[rs].t=0.0;
tr[ls].x=tr[ls].y=(tr[ls].l+tr[ls].r)*(tr[ls].r-tr[ls].l+1)/2.0;
tr[rs].x=tr[rs].y=(tr[rs].l+tr[rs].r)*(tr[rs].r-tr[rs].l+1)/2.0;
tr[ls].xx=tr[ls].xy=sum(tr[ls].l,tr[ls].r);
tr[rs].xx=tr[rs].xy=sum(tr[rs].l,tr[rs].r);
tr[pos].cov=0;
}
tr[ls].s+=tr[pos].s,tr[rs].s+=tr[pos].s;
tr[ls].t+=tr[pos].t,tr[rs].t+=tr[pos].t;
tr[ls].xx+=2*tr[pos].s*tr[ls].x+tr[pos].s*tr[pos].s*(tr[ls].r-tr[ls].l+1);
tr[rs].xx+=2*tr[pos].s*tr[rs].x+tr[pos].s*tr[pos].s*(tr[rs].r-tr[rs].l+1);
tr[ls].xy+=tr[pos].s*tr[ls].y+tr[pos].t*tr[ls].x+tr[pos].s*tr[pos].t*(tr[ls].r-tr[ls].l+1);
tr[rs].xy+=tr[pos].s*tr[rs].y+tr[pos].t*tr[rs].x+tr[pos].s*tr[pos].t*(tr[rs].r-tr[rs].l+1);
tr[ls].x+=tr[pos].s*(tr[ls].r-tr[ls].l+1);
tr[rs].x+=tr[pos].s*(tr[rs].r-tr[rs].l+1);
tr[ls].y+=tr[pos].t*(tr[ls].r-tr[ls].l+1);
tr[rs].y+=tr[pos].t*(tr[rs].r-tr[rs].l+1);
tr[pos].s=tr[pos].t=0;
}
void build(int pos,int l,int r){
tr[pos].l=l,tr[pos].r=r;
if(l==r){
tr[pos].x=a[l],tr[pos].y=b[l];
tr[pos].xx=a[l]*a[l],tr[pos].xy=a[l]*b[l];
return;
}
build(ls,l,mid);
build(rs,mid+1,r);
push_u(pos);
}
void update(int pos,int l,int r,double s,double t){
if(l<=tr[pos].l&&tr[pos].r<=r){
tr[pos].s+=s,tr[pos].t+=t;
tr[pos].xx+=2*s*tr[pos].x+s*s*(tr[pos].r-tr[pos].l+1);
tr[pos].xy+=s*tr[pos].y+t*tr[pos].x+s*t*(tr[pos].r-tr[pos].l+1);
tr[pos].x+=s*(tr[pos].r-tr[pos].l+1);
tr[pos].y+=t*(tr[pos].r-tr[pos].l+1);
return;
}
push_d(pos);
if(l<=mid) update(ls,l,r,s,t);
if(mid<r) update(rs,l,r,s,t);
push_u(pos);
}
void update(int pos,int l,int r){
if(l<=tr[pos].l&&tr[pos].r<=r){
tr[pos].cov=1,tr[pos].s=tr[pos].t=0.0;
tr[pos].x=tr[pos].y=(tr[pos].l+tr[pos].r)*(tr[pos].r-tr[pos].l+1)/2.0;
tr[pos].xx=tr[pos].xy=sum(tr[pos].l,tr[pos].r);
return;
}
push_d(pos);
if(l<=mid) update(ls,l,r);
if(mid<r) update(rs,l,r);
push_u(pos);
}
double qry(int pos,int l,int r,int op){
if(l<=tr[pos].l&&tr[pos].r<=r){
if(op==1) return tr[pos].x;
if(op==2) return tr[pos].y;
if(op==3) return tr[pos].xx;
if(op==4) return tr[pos].xy;
return 1;
}
double cur=0.0;
push_d(pos);
if(l<=mid) cur+=qry(ls,l,r,op);
if(mid<r) cur+=qry(rs,l,r,op);
return cur;
}
}using namespace Segtree;
int main(){
// ios::sync_with_stdio(0);
// cin.tie(0),cout.tie(0);
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n;i++) cin>>b[i];
build(1,1,n);
int op,l,r; double s,t;
while(m--){
cin>>op>>l>>r;
if(op==2){
cin>>s>>t;
update(1,l,r,s,t);
}
else if(op==3){
cin>>s>>t;
update(1,l,r);
update(1,l,r,s,t);
}
else{
double x=qry(1,l,r,1);
double y=qry(1,l,r,2);
double xx=qry(1,l,r,3);
double xy=qry(1,l,r,4);
printf("%.12f\n",(xy*(r-l+1)-x*y)/(xx*(r-l+1)-x*x));
// printf("%.12f %.12f %.12f %.12f\n------------------\n",x,y,xx,xy);
}
}
return 0;
}