[线段树]JZOJ 4231 寻找神格
分析
修仙小说即视感
以前写过类似的题解,这是传送门
精度有问题,SPJ没有说明,需要输出超过3位小数
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream> #include <cstdio> #define lson x<<1 #define rson (x<<1)+1 using namespace std; typedef long long ll; const int N=1e5+10; struct Seg { int l,r; double sum,msum,lz; }t[4*N]; int a[N]; int n,q; double ans1,ans2; void Pushdown(int x) { if (!x||!t[x].lz) return; t[lson].lz+=t[x].lz;t[lson].msum+=(t[lson].r-t[lson].l+1.0)*t[x].lz*t[x].lz+2.0*t[x].lz*t[lson].sum; t[lson].sum+=(t[lson].r-t[lson].l+1.0)*t[x].lz; t[rson].lz+=t[x].lz;t[rson].msum+=(t[rson].r-t[rson].l+1.0)*t[x].lz*t[x].lz+2.0*t[x].lz*t[rson].sum; t[rson].sum+=(t[rson].r-t[rson].l+1.0)*t[x].lz; t[x].lz=0; } void Build(int x,int l,int r) { t[x].l=l;t[x].r=r; if (l==r) { t[x].sum=a[l];t[x].msum=1.0*a[l]*a[l]; return; } int mid=l+r>>1; Build(lson,l,mid);Build(rson,mid+1,r); t[x].msum=t[lson].msum+t[rson].msum; t[x].sum=t[lson].sum+t[rson].sum; } void Change(int x,int l,int r,int xl,int xr,int b) { if (l>xr||xl>r||l>r) return; if (xl<=l&&r<=xr) { t[x].msum+=(r-l+1.0)*b*b+2.0*b*t[x].sum;t[x].sum+=(r-l+1.0)*b; t[x].lz+=b; return; } Pushdown(x); int mid=l+r>>1; if (xl<=mid) Change(lson,l,mid,xl,xr,b); if (mid<xr) Change(rson,mid+1,r,xl,xr,b); t[x].msum=t[lson].msum+t[rson].msum; t[x].sum=t[lson].sum+t[rson].sum; } void Query(int x,int l,int r,int xl,int xr) { if (l>xr||xl>r||l>r) return; if (xl<=l&&r<=xr) { ans1+=t[x].sum;ans2+=t[x].msum; return; } Pushdown(x); int mid=l+r>>1; if (xl<=mid) Query(lson,l,mid,xl,xr); if (mid<xr) Query(rson,mid+1,r,xl,xr); } int main() { scanf("%d%d",&n,&q); for (int i=1;i<=n;i++) scanf("%d",&a[i]); Build(1,1,n); for (int i=1;i<=q;i++) { int order,l,r,c; scanf("%d%d%d",&order,&l,&r); if (order==0) Change(1,1,n,l,l,r); else if (order==1) scanf("%d",&c),Change(1,1,n,l,r,c); else { ans1=ans2=0; Query(1,1,n,l,r); if (order==2) printf("%lld\n",(ll)ans1); else printf("%.10lf\n",1.0*ans2/(r-l+1.0)-1.0*ans1*ans1/((r-l+1.0)*(r-l+1.0))); } } }
在日渐沉没的世界里,我发现了你。