JZOJ 4231. 寻找神格
题目
大意
很难讲,慢慢看吧
分析
这道题是一个线段树 可以单点修改,区间修改,区间查询
第一二问其实就是建一个数罢了
第三问 也就是查找有线段树区间是否覆盖罢了
第四问 才是关键:
首先我们要求方差 就要求出总和,然后我们该如何在区间修改其他值呢?
开一个数组add,记录每一次修改的值,在每一次查找的时候将其他值一起覆盖
[p]=[p*2]+[p*2+1];
代码
#include<iostream> #include<cstdio> #define ll long long using namespace std; ll n,m; ll sum[10000010],num[1000010],add[1000010]; double ans; void tj(ll p,ll l,ll r,ll a,ll b,ll x) { if (l==a&&r==b){ sum[p]+=x*x*(r-l+1)+2*num[p]*x; num[p]+=x*(r-l+1); add[p]+=x; return; } ll mid=(l+r)/2; if (add[p]){ sum[p*2]+=add[p]*add[p]*(mid-l+1)+2*num[p*2]*add[p]; num[p*2]+=add[p]*(mid-l+1); add[p*2]+=add[p*2]+add[p]; sum[p*2+1]+=add[p]*add[p]*(r-mid)+2*num[p*2+1]*add[p]; num[p*2+1]+=add[p]*(r-mid); add[p*2+1]+=add[p]; add[p]=0; } if (b<=mid) tj(p*2,l,mid,a,b,x); else if (a>mid) tj(p*2+1,mid+1,r,a,b,x); else{ tj(p*2,l,mid,a,mid,x); tj(p*2+1,mid+1,r,mid+1,b,x); } sum[p]=sum[p*2]+sum[p*2+1]; num[p]=num[p*2]+num[p*2+1]; } ll h=0; ll check1(ll p,ll l,ll r,ll a,ll b) { if (l==a&&r==b) { return num[p]; } ll mid=(l+r)/2; if (add[p]){ sum[p*2]=sum[p*2]+add[p]*add[p]*(mid-l+1)+2*num[p*2]*add[p]; num[p*2]=num[p*2]+add[p]*(mid-l+1); add[p*2]=add[p*2]+add[p]; sum[p*2+1]=sum[p*2+1]+add[p]*add[p]*(r-mid)+2*num[p*2+1]*add[p]; num[p*2+1]=num[p*2+1]+add[p]*(r-mid); add[p*2+1]=add[p*2+1]+add[p]; add[p]=0; } if (b<=mid) return check1(p*2,l,mid,a,b); else if (a>mid) return check1(p*2+1,mid+1,r,a,b); else{ return check1(p*2,l,mid,a,mid)+check1(p*2+1,mid+1,r,mid+1,b); } } ll hh=0; ll check2(ll p,ll l,ll r,ll a,ll b) { if (l==a&&r==b) { return sum[p]; } ll mid=(l+r)/2; if (add[p]){ sum[p*2]=sum[p*2]+add[p]*add[p]*(mid-l+1)+2*num[p*2]*add[p]; num[p*2]=num[p*2]+add[p]*(mid-l+1); add[p*2]=add[p*2]+add[p]; sum[p*2+1]=sum[p*2+1]+add[p]*add[p]*(r-mid)+2*num[p*2+1]*add[p]; num[p*2+1]=num[p*2+1]+add[p]*(r-mid); add[p*2+1]=add[p*2+1]+add[p]; add[p]=0; } if (b<=mid) return check2(p*2,l,mid,a,b); else if (a>mid) return check2(p*2+1,mid+1,r,a,b); else{ return check2(p*2,l,mid,a,mid)+check2(p*2+1,mid+1,r,mid+1,b); } } int main () { cin>>n>>m; ll x; for (int i=1;i<=n;i++) { cin>>x; tj(1,1,n,i,i,x); } ll t,a,b,c; double ans; for (int i=1;i<=m;i++) { cin>>t; if (t==0) { cin>>a>>b; tj(1,1,n,a,a,b); } if (t==1) { cin>>a>>b>>c; tj(1,1,n,a,b,c); } if (t==2) { cin>>a>>b; cout<<check1(1,1,n,a,b)<<endl; } if (t==3) { cin>>a>>b; ll h=check1(1,1,n,a,b); ll hh=check2(1,1,n,a,b); double x=h,y=hh,z=(b-a+1); ans=(double)y*z; ans=(double)(ans-(double)x*x); ans=(double)ans/((double)z*z); printf("%.10lf\n",ans); } } }
为何要逼自己长大,去闯不该闯的荒唐