那是上上周。。。也是重构了四遍。。。后来GG了。。。今天又拾起,搞了搞终于过了。。。
好吧就是个线段树,公式懒得推了https://www.cnblogs.com/Jackpei/p/10693561.html大致差不错
#include<iostream> #include<cstdio> #define R register int #define ls (tr<<1) #define rs (tr<<1|1) using namespace std; int n,m; double sum[400001],po[400001],tg[400001]; inline void upd(int tr){sum[tr]=sum[ls]+sum[rs]; po[tr]=po[ls]+po[rs];} inline void build(int tr,int l,int r) { if(l==r) {scanf("%lf",&sum[tr]),po[tr]=sum[tr]*sum[tr]; return ;} R md=l+r>>1; build(ls,l,md),build(rs,md+1,r); upd(tr); } inline void change(int tr,int l,int r,double d) {po[tr]+=d*(d*(r-l+1)+2.0*sum[tr]),sum[tr]+=(r-l+1)*d;} inline void spread(int tr,int l,int r) { R md=l+r>>1; if(tg[tr]) change(ls,l,md,tg[tr]),change(rs,md+1,r,tg[tr]),tg[ls]+=tg[tr],tg[rs]+=tg[tr],tg[tr]=0; } inline void update(int tr,int l,int r,int LL,int RR,double d){ if(LL<=l&&r<=RR) {tg[tr]+=d,change(tr,l,r,d);return;} spread(tr,l,r); R md=l+r>>1; if(LL<=md) update(ls,l,md,LL,RR,d); if(RR>md) update(rs,md+1,r,LL,RR,d); upd(tr); } inline double query1(int tr,int l,int r,int LL,int RR){ if(LL<=l&&r<=RR) return sum[tr]; spread(tr,l,r); R md=l+r>>1; register double ret=0; if(LL<=md) ret+=query1(ls,l,md,LL,RR); if(RR>md) ret+=query1(rs,md+1,r,LL,RR); return ret; } inline double query2(int tr,int l,int r,int LL,int RR){ if(LL<=l&&r<=RR) return po[tr]; spread(tr,l,r); R md=l+r>>1; register double ret=0; if(LL<=md) ret+=query2(ls,l,md,LL,RR); if(RR>md) ret+=query2(rs,md+1,r,LL,RR); return ret; } inline void solve1(int l,int r){printf("%.4lf ",query1(1,1,n,l,r)/(double)(r-l+1));} inline void solve2(int l,int r){ double ave=query1(1,1,n,l,r)/(double)(r-l+1),x=query2(1,1,n,l,r),s=query1(1,1,n,l,r); printf("%.4lf ",(x+(double)(r-l+1)*ave*ave-2.0*s*ave)/(double)(r-l+1)); } signed main(){ scanf("%d%d",&n,&m); build(1,1,n); for(int i=1;i<=m;++i){ R k,l,r; register double d; scanf("%d%d%d",&k,&l,&r); if(k==1) scanf("%lf",&d),update(1,1,n,l,r,d); else if(k==2) solve1(l,r); else solve2(l,r); } }
2019.04.22 唉QAQ...