洛谷P1471 方差(线段树lazy维护区间平均数和区间方差)
【洛谷P1471 方差(线段树lazy维护区间平均数和区间方差)】题意:传送门
题解:三种操作:一是区间加,使用lazy操作即可完成,而是平均数,使用区间加维护,三是区间方差,将公式展开,发现 s 2 = 1 n ? ( ∑ i = x i = y a i 2 ? 2 ? a  ̄ ? ∑ i = x i = y a i + ( y ? x + 1 ) ? a  ̄ ) s^2=\frac{1}{n}*(\sum_{i=x}^{i=y}a_{i}^2-2*\overline{a}*\sum_{i=x}^{i=y}a_{i}+(y-x+1)*\overline{a}) s2=n1??(∑i=xi=y?ai2??2?a?∑i=xi=y?ai?+(y?x+1)?a),所以再多维护一个区间平方和即可。
#include
using namespace std;
const int maxn=1e5+5;
int n,m,t,x,y;
double z;
struct data{
int l,r;
double sum,ssum,add;
}tree[maxn<<2];
void update(int k)
{
tree[k].sum=tree[k<<1].sum+tree[k<<1|1].sum;
tree[k].ssum=tree[k<<1].ssum+tree[k<<1|1].ssum;
}
void pushdown(int k,int x)
{
if(tree[k].add){
tree[k<<1].ssum+=2*tree[k].add*tree[k<<1].sum+tree[k].add*tree[k].add*(x-x/2);
tree[k<<1|1].ssum+=2*tree[k].add*tree[k<<1|1].sum+tree[k].add*tree[k].add*(x/2);
tree[k<<1].sum+=(x-x/2)*tree[k].add;
tree[k<<1|1].sum+=(x/2)*tree[k].add;
tree[k<<1].add+=tree[k].add;
tree[k<<1|1].add+=tree[k].add;
tree[k].add=0;
}
}
void build(int k,int s,int t)
{
tree[k].l=s;
tree[k].r=t;
if(s==t){scanf("%lf",&tree[k].sum);
tree[k].ssum=tree[k].sum*tree[k].sum;
return ;
}
int mid=(s+t)>>1;
build(k<<1,s,mid);
build(k<<1|1,mid+1,t);
update(k);
}
void change(int k,int p,int q,double y)
{
int l=tree[k].l,r=tree[k].r;
if(l==p&&r==q){
tree[k].ssum+=2*y*tree[k].sum+(r-l+1)*y*y;
tree[k].sum+=(r-l+1)*y;
tree[k].add+=y;
return ;
}
pushdown(k,r-l+1);
int mid=(l+r)>>1;
if(q<=mid)change(k<<1,p,q,y);
else if(p>mid)change(k<<1|1,p,q,y);
else{
change(k<<1,p,mid,y);
change(k<<1|1,mid+1,q,y);
}
update(k);
}
double ask1(int k,int p,int q)
{
int l=tree[k].l,r=tree[k].r;
if(l==p&&r==q)return tree[k].sum;
pushdown(k,r-l+1);
int mid=(l+r)>>1;
if(q<=mid)return ask1(k<<1,p,q);
else if(p>mid)return ask1(k<<1|1,p,q);
else{
return ask1(k<<1,p,mid)+ask1(k<<1|1,mid+1,q);
}
}
double ask2(int k,int p,int q)
{
int l=tree[k].l,r=tree[k].r;
if(l==p&&r==q)return tree[k].ssum;
pushdown(k,r-l+1);
int mid=(l+r)>>1;
if(q<=mid)return ask2(k<<1,p,q);
else if(p>mid)return ask2(k<<1|1,p,q);
else{
return ask2(k<<1,p,mid)+ask2(k<<1|1,mid+1,q);
}
}
int main()
{
scanf("%d%d",&n,&m);
build(1,1,n);
for(int i=0;
i
推荐阅读
- Opencv基础图像处理|OTSU算法(大津法—最大类间方差法)原理及实现
- 考虑交互作用&误差变动的设计方案以及协方差
- 水题纪念|【51nod - 1098】 最小方差(基础数学,公式化简,前缀和,积的前缀和)
- 洛谷 P5056 【模板】插头dp
- C++|【暖*墟】 #洛谷省选网课# 8.1数论进阶
- 数据变异性的度量|数据变异性的度量 - 极差、IQR、方差和标准偏差
- 洛谷|洛谷 P1481 魔族密码
- SP694 DISUBSTR - Distinct Substrings(洛谷 字典树)
- KD-Tree|【NOI2019】【LOJ3259】【洛谷P5471】弹跳(K-D Tree)(最短路)
- JSOI2018冬令营游记&总结(迁移自洛谷博客)