题目大意:维护一个有 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. 20155311高梓云《网络对抗》逆向及Bof基础

    20155311高梓云<网络对抗>逆向及Bof基础 实践目标 本次实践的对象是一个名为pwn1的linux可执行文件. 该程序正常执行流程是:main调用foo函数,foo函数会简单回显任 ...

  2. Android开发——Android多进程以及使用场景介绍

    个层级,具体可以查看Android开发--Android进程保活招式大全中1.1部分的内容,这里就不赘述了. 根据进程中当前活动组件的重要程度,Android 会将进程评定为它可能达到的最高级别.例如 ...

  3. SQL Server Integration Services的10大最佳实践

    原文出处:https://blogs.msdn.microsoft.com/sqlcat/2013/09/16/top-10-sql-server-integration-services-best- ...

  4. 机器学习英雄访谈录之双料 Kaggle 大师:Dr. Jean-Francois Puget

    目录 机器学习英雄访谈录之双料 Kaggle 大师:Dr. Jean-Francois Puget 正文 对我的启发 机器学习英雄访谈录之双料 Kaggle 大师:Dr. Jean-Francois ...

  5. GitHub笔记(一)——本地库基础操作

    零.基础概念理解——可以访问廖雪峰老师的网站https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c01 ...

  6. Tomcat源码学习(1)

    Tomcat源码学习(1) IntelliJ IDEA 17.3.3 导入 Tomcat 9.0.6源码 下载源码 tomcat_9.0.6 启动 IDEA. 点击 Open,选择刚才下载的文件解压后 ...

  7. Nuxeo 认证绕过和RCE漏洞分析(CVE-2018-16341)

    简介 Nuxeo Platform是一款跨平台开源的企业级内容管理系统(CMS).nuxeo-jsf-ui组件处理facelet模板不当,当访问的facelet模板不存在时,相关的文件名会输出到错误页 ...

  8. 制作R中分词的字典的办法

    在开始下面步骤之前先让自己的文件可以显示扩展名. 如何显示请谷歌. 第一步:打开一个文本文件 第二步:把你要的词复制到这个文本文件吧. 第三步:将这个文本文件的格式改为dic.即原来文件格式是txt后 ...

  9. Test Cases

    对于mode1 1 路径下一个空文件夹       结果:生成一个空的txt 2路径下一个文件夹内包含一个txt内容为abd(最基本的一个单词) 3路径下一个空文件夹一个txt,txt内容为以不同符号 ...

  10. Linux读书笔记第三、四章

    第三章 主要内容: 进程和线程 进程的生命周期 进程的创建 进程的终止 1. 进程和线程 进程和线程是程序运行时状态,是动态变化的,进程和线程的管理操作(比如,创建,销毁等)都是有内核来实现的. Li ...