[luogu]P1471 方差

 https://www.luogu.org/problemnew/show/P1471

线段树+展开方差公式+完全平方公式

我们把方差公式展开

所以只需要维护一个区间平方和和区间和

当我们更新一个区间加时

所以pushdown就很好写了

代码:

 1 #include<bits/stdc++.h>
 2 #define ll int
 3 #define db double
 4 #define max(x,y) ((x)>(y)?(x):(y))
 5 #define min(x,y) ((x)<(y)?(x):(y))
 6 #define fur(i,x,y) for(i=x;i<=y;i++)
 7 #define fdr(i,x,y) for(i=x;i>=y;i--)
 8 #define Fur(i,x,y) for(ll i=x;i<=y;i++)
 9 #define Fdr(i,x,y) for(ll i=x;i>=y;i--)
10 #define in2(x,y) in(x);in(y)
11 #define in3(x,y,z) in2(x,y);in(z)
12 #define in4(a,b,c,d) in2(a,b);in2(c,d)
13 #define clr(x,y) memset(x,y,sizeof(x))
14 #define cpy(x,y) memcpy(x,y,sizeof(x))
15 #define fl(i,x) for(ll i=head[x],to;to=e[i].to,i;i=e[i].next)
16 #define inf 233333333
17 using namespace std;
18 /*---------------------------------------*/
19 #define pob (fwrite(fob::b,sizeof(char),fob::f-fob::b,stdout),fob::f=fob::b,0)
20 #define pc(x) (*(fob::f++)=(x),(fob::f==fob::g)?pob:0)
21 #define gc ((*fib::f)?(*(fib ::f++)):(fgets(fib::b,sizeof(fib::b),stdin)?(fib::f=fib::b,*(fib::f++)):-1))
22 namespace fib{char b[300000]= {},*f=b;}inline void in(ll &x){x=0;char c;bool f=0;while((c=gc)>'9'||c<'0')if(c=='-')f=!f;x=c-48;while((c=gc)<='9'&&c>='0')x=x*10+c-48;if(f)x=-x;}namespace fob{char b[300000]= {},*f=b,*g=b+300000-2;}struct foce{~foce(){pob;fflush(stdout);}} _foce;namespace ib{char b[100];}inline void out(ll x){if(x==0){pc(48);return;}if(x<0){pc('-');x=-x;}char *s=ib::b;while(x) *(++s)=x%10,x/=10;while(s!=ib::b) pc((*(s--))+48);}inline void outn(ll x){out(x);pc('
');}
23 inline void swap(ll &x,ll &y){ll t=x;x=y;y=t;}
24 inline ll jdz(ll x){return x>=0?x:-x;}
25 /*------------------------------------------------------------------------------------------------*/
26 //上面全是自定义
27 #define N 110000
28 #define idb(x) scanf("%lf",&x)
29 #define Z ll m=(l+r)>>1
30 #define P(x) ((x)*(x))
31 #define ls rt<<1
32 #define rs rt<<1|1
33 #define pu s[rt]=s[ls]+s[rs];ap[rt]=ap[ls]+ap[rs]
34 //pushup向上更新
35 db a[N],s[N<<2],ap[N<<2],add[N<<2];
36 //a为原数组,s为区间和,ap为区间中每个数的平方的和,add为懒惰标记
37 ll n,q;
38 inline void pd(ll rt,ll ln,ll rn){
39     if(add[rt]){
40         add[ls]+=add[rt];add[rs]+=add[rt];
41         ap[ls]+=P(add[rt])*ln+2*s[ls]*add[rt];
42         ap[rs]+=P(add[rt])*rn+2*s[rs]*add[rt];
43         s[ls]+=add[rt]*ln;s[rs]+=add[rt]*rn;
44         add[rt]=0;
45     }
46 }//pushdown下推
47 inline void build(ll l,ll r,ll rt){
48     if(l==r){s[rt]=a[l];ap[rt]=P(a[l]);return;}
49     Z;build(l,m,ls);build(m+1,r,rs);pu;
50 }
51 inline void upd(ll L,ll R,db c,ll l,ll r,ll rt){
52     if(L<=l&&r<=R){
53         ap[rt]+=(c*c*(r-l+1)+2*s[rt]*c);
54         s[rt]+=((r-l+1)*c);
55         add[rt]+=c;
56         return;
57     }
58     Z;pd(rt,m-l+1,r-m);
59     if(L<=m)upd(L,R,c,l,m,ls);
60     if(R>m)upd(L,R,c,m+1,r,rs);
61     pu;
62 }
63 inline db qs(ll L,ll R,ll l,ll r,ll rt){
64     if(L<=l&&r<=R)return s[rt];
65     Z;db ans=0;pd(rt,m-l+1,r-m);
66     if(L<=m)ans+=qs(L,R,l,m,ls);
67     if(R>m)ans+=qs(L,R,m+1,r,rs);
68     return ans;
69 }
70 inline db qp(ll L,ll R,ll l,ll r,ll rt){
71     if(L<=l&&r<=R)return ap[rt];
72     Z;db ans=0;pd(rt,m-l+1,r-m);
73     if(L<=m)ans+=qp(L,R,l,m,ls);
74     if(R>m)ans+=qp(L,R,m+1,r,rs);
75     return ans;
76 }
77 int main(){
78     ll u,x,y,t;
79     db sa,sp,ans,c;
80     cin>>n>>q;
81     Fur(i,1,n)idb(a[i]);
82     build(1,n,1);
83     while(q--){
84         scanf("%d%d%d",&u,&x,&y);
85         if(u==1){idb(c);upd(x,y,c,1,n,1);continue;}
86         if(u==2)ans=qs(x,y,1,n,1)/(y-x+1);
87         if(u==3){
88             sa=qs(x,y,1,n,1)/(y-x+1);sp=qp(x,y,1,n,1)/(y-x+1);
89 //sa为平均数,sp为每个数的平方的平均数
90             ans=sp-sa*sa;
91         }//求方差
92         printf("%.4lf
",ans);
93     }
94 }
代码
原文地址:https://www.cnblogs.com/mimiorz/p/9128283.html