题目大意:维护一个有 N 个元素的序列,支持以下操作:区间加,区间询问均值,区间询问方差。

题解:可知区间均值和区间和有关,即:维护区间和就等于维护了区间均值。区间方差表达式为 $$\frac{\Sigma_{i=1}n(a[i]-aver)2}{n}$$,化简之后可知还需维护区间的平方和。

这道题说明了,对于线段树来说,维护的东西并不一定直接是需要维护的东西,可以维护一些间接的信息,最后综合到一起计算得到需要维护的答案。

代码如下

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+10; int n,q;
double a[maxn]; struct node{int lc,rc;double tag,sum,sum2;};
struct segment_tree{
#define ls t[k].lc
#define rs t[k].rc
node t[maxn<<1];
int tot;
segment_tree():tot(1){memset(t,0,sizeof(t));}
inline void pushup(int k){
t[k].sum=t[ls].sum+t[rs].sum;
t[k].sum2=t[ls].sum2+t[rs].sum2;
}
inline void pushdown(int k,int l,int r){
int mid=l+r>>1;
t[ls].sum2+=(mid-l+1)*t[k].tag*t[k].tag+2*t[k].tag*t[ls].sum;
t[ls].sum+=(mid-l+1)*t[k].tag;
t[ls].tag+=t[k].tag;
t[rs].sum2+=(r-mid)*t[k].tag*t[k].tag+2*t[k].tag*t[rs].sum;
t[rs].sum+=(r-mid)*t[k].tag;
t[rs].tag+=t[k].tag;
t[k].tag=0;
}
void build(int k,int l,int r){
if(l==r){t[k].sum=a[l],t[k].sum2=a[l]*a[l];return;}
int mid=l+r>>1;
ls=++tot,build(ls,l,mid);
rs=++tot,build(rs,mid+1,r);
pushup(k);
}
void modify(int k,int l,int r,int x,int y,double val){
if(l==x&&r==y){
t[k].sum2+=2*val*t[k].sum+(r-l+1)*val*val;
t[k].sum+=(r-l+1)*val;
t[k].tag+=val;
return;
}
int mid=l+r>>1;
pushdown(k,l,r);
if(y<=mid)modify(ls,l,mid,x,y,val);
else if(x>mid)modify(rs,mid+1,r,x,y,val);
else modify(ls,l,mid,x,mid,val),modify(rs,mid+1,r,mid+1,y,val);
pushup(k);
}
double query1(int k,int l,int r,int x,int y){
if(l==x&&r==y)return t[k].sum;
int mid=l+r>>1;
pushdown(k,l,r);
if(y<=mid)return query1(ls,l,mid,x,y);
else if(x>mid)return query1(rs,mid+1,r,x,y);
else return query1(ls,l,mid,x,mid)+query1(rs,mid+1,r,mid+1,y);
}
double query2(int k,int l,int r,int x,int y){
if(l==x&&r==y)return t[k].sum2;
int mid=l+r>>1;
pushdown(k,l,r);
if(y<=mid)return query2(ls,l,mid,x,y);
else if(x>mid)return query2(rs,mid+1,r,x,y);
else return query2(ls,l,mid,x,mid)+query2(rs,mid+1,r,mid+1,y);
}
double mean(int l,int r){return this->query1(1,1,n,l,r)/(r-l+1);}
double var(int l,int r){
double tmp=this->mean(l,r);
double tmp2=this->query2(1,1,n,l,r);
return tmp2/(r-l+1)-tmp*tmp;
}
}sgt; void read_and_parse(){
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++)scanf("%lf",&a[i]);
sgt.build(1,1,n);
} void solve(){
int opt,x,y;
double k;
while(q--){
scanf("%d",&opt);
if(opt==1){
scanf("%d%d%lf",&x,&y,&k);
sgt.modify(1,1,n,x,y,k);
}else if(opt==2){
scanf("%d%d",&x,&y);
printf("%.4lf\n",sgt.mean(x,y));
}else if(opt==3){
scanf("%d%d",&x,&y);
printf("%.4lf\n",sgt.var(x,y));
}
}
} int main(){
read_and_parse();
solve();
return 0;
}

【洛谷P1471】方差的更多相关文章

  1. 洛谷 P1471 方差

    洛谷 P1471 方差 题目背景 滚粗了的HansBug在收拾旧数学书,然而他发现了什么奇妙的东西. 题目描述 蒟蒻HansBug在一本数学书里面发现了一个神奇的数列,包含N个实数.他想算算这个数列的 ...

  2. 洛谷P1471 方差

    蒟蒻HansBug在一本数学书里面发现了一个神奇的数列,包含N个实数.他想算算这个数列的平均数和方差. ——by 洛谷; http://www.luogu.org/problem/show?pid=1 ...

  3. 洛谷——P1471 方差

    P1471 方差 题目描述 蒟蒻HansBug在一本数学书里面发现了一个神奇的数列,包含N个实数.他想算算这个数列的平均数和方差. 借一下远航之曲大佬的图片,特别清晰: 那么只要维护区间平方和,就可以 ...

  4. 2018.08.16 洛谷P1471 方差(线段树)

    传送门 线段树基本操作. 把那个方差的式子拆开可以发现只用维护一个区间平方和和区间和就可以完成所有操作. 同样区间修改也可以简单的操作. 代码: #include<bits/stdc++.h&g ...

  5. AC日记——方差 洛谷 P1471

    方差 思路: 线段树: 代码: #include <bits/stdc++.h> using namespace std; #define maxn 100005 struct TreeN ...

  6. 【洛谷】【线段树】P1471 方差

    [题目背景:] 滚粗了的HansBug在收拾旧数学书,然而他发现了什么奇妙的东西. [题目描述:] 蒟蒻HansBug在一本数学书里面发现了一个神奇的数列,包含N个实数.他想算算这个数列的平均数和方差 ...

  7. 洛谷P4072 [SDOI2016]征途(带权二分,斜率优化)

    洛谷题目传送门 一开始肯定要把题目要求的式子给写出来 我们知道方差的公式\(s^2=\frac{\sum\limits_{i=1}^{m}(x_i-\overline x)^2}{m}\) 题目要乘\ ...

  8. 洛谷NOIp热身赛题解

    洛谷NOIp热身赛题解 A 最大差值 简单树状数组,维护区间和.区间平方和,方差按照给的公式算就行了 #include<bits/stdc++.h> #define il inline # ...

  9. 洛谷 P4072 [SDOI2016]征途 斜率优化DP

    洛谷 P4072 [SDOI2016]征途 斜率优化DP 题目描述 \(Pine\) 开始了从 \(S\) 地到 \(T\) 地的征途. 从\(S\)地到\(T\)地的路可以划分成 \(n\) 段,相 ...

随机推荐

  1. 20155237 2016-2017-2 《Java程序设计》第十周学习总结

    20155237 2016-2017-2 <Java程序设计>第十周学习总结 教材学习内容总结 计算机网络,是指分布在不同地理区域的计算机用通信线路互连起来的一个具有强大功能的网络系统.网 ...

  2. 20155304田宜楠《网络对抗技术》Exp1 PC平台逆向破解(5)M

    Exp1 PC平台逆向破解(5)M 实践目标 本次实践的对象是一个名为pwn1的linux可执行文件. 该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何用户输入的字符串. 该程序 ...

  3. 汇编 do while循环

    do while生成的汇编代码  do while汇编还原成C++代码 一. do while成生的汇编代码 // int i=0; // do // { // i++; // } while ( ...

  4. 单片机程序在内存和FLASH中的空间分配

    本文转载于的tietao的博客!!!http://blog.csdn.net/tietao/article/details/8172411 *******防止自己忘记,固备之. 一句话:基于速度问题, ...

  5. python3获取指定目录内容的详细信息

    不同平台获取指定目录内容的详细信息命令各不相同: Linux中可以通过ls -al获取获取 windows中可以通过dir命令获取 下面是我写的一个通用获取目录内容详细信息的python3脚本: #! ...

  6. [LOJ#6039].「雅礼集训 2017 Day5」珠宝[决策单调性]

    题意 题目链接 分析 注意到本题的 \(C\) 很小,考虑定义一个和 \(C\) 有关的状态. 记 \(f(x,j)\) 表示考虑到了价格为 \(x\) 的物品,一共花费了 \(j\) 元的最大收益. ...

  7. JavaScript快速入门-ECMAScript本地对象(Number)

    Number 对象是原始数值的包装对象. 创建一个Number对象:var myNum=new Number(value); 注意: 1.参数 value 是要创建的 Number 对象的数值,或是要 ...

  8. grunt源码解析:整体运行机制&grunt-cli源码解析

    前端的童鞋对grunt应该不陌生,前面也陆陆续续的写了几篇grunt入门的文章.本篇文章会更进一步,对grunt的源码进行分析.文章大体内容内容如下: grunt整体设计概览 grunt-cli源码分 ...

  9. Jenkins下载安装

    Jenkins是什么? Jenkins是一个功能强大的应用程序,允许持续集成和持续交付项目,无论用的是什么平台.这是一个免费的源代码,可以处理任何类型的构建或持续集成.集成Jenkins可以用于一些测 ...

  10. Ubuntu Google Chrome

    Chrome安装 添加下载源 sudo wget http://www.linuxidc.com/files/repo/google-chrome.list -P /etc/apt/sources.l ...