JZOJ 4231. 尋找神格 (Standard IO)
阿新 • • 發佈:2019-01-22
out for n-1 記錄 tput 發生 field fine 一個人
題目
大意
很難講,慢慢看吧
分析
這道題是一個線段樹 可以單點修改,區間修改,區間查詢
第一二問其實就是建一個數罷了
第三問 也就是查找有線段樹區間是否覆蓋罷了
第四問 才是關鍵:
首先我們要求方差 就要求出總和,然後我們該如何在區間修改其他值呢?
開一個數組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); } } }
JZOJ 4231. 尋找神格 (Standard IO)