Loj 2005 相关分析

  • 大力把式子拆开.

\[\begin{aligned}
a &= \frac {\sum_{i=L}^{R} (x_i-\bar{x})(y_i-\bar{y})} {\sum_{i=L}^{R} (x_i-\bar{x})^2}\\
&= \frac {\sum_{i=L}^R (x_iy_i+\bar{x}\bar{y}-\bar{x}y_i-\bar{y}x_i)} {\sum_{i=L}^{R} (x_i^2-2\bar{x}x_i+\bar{x}^2)}\\
&=\frac {\sum_{i=L}^R x_iy_i+(R-L+1)\cdot\bar{x}\bar{y}-\bar{x}\sum_{i=L}^{R}y_i-\bar{y}\sum_{i=L}^{R}x_i} {\sum_{i=L}^{R} x_i^2-2\bar{x}\sum_{i=L}^{R}x_i+(R-L+1)*\bar{x}^2}
\end{aligned}
\]

  • 于是只需要用线段树维护区间的 \(\sum x_i,\sum y_i,\sum x_i y_i,\sum x_i^2\) .
  • 考虑两种修改操作,第一种显然很简单,第二种可以看成对区间执行 \(x_i=i,y_i=i\) ,再进行第一种操作.修改之后这四个值都可以利用公式 \(O(1)\) 算出.于是维护三个标记就可以了.
  • 注意中间运算时开 \(long\ long,double\) ,防止爆掉.

其实代码写得有些冗长.可以把结果和标记写在两个数组中,这样修改查询的时候传入下标应该会短不少.

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
inline int read()
{
int out=0,fh=1;
char jp=getchar();
while ((jp>'9'||jp<'0')&&jp!='-')
jp=getchar();
if (jp=='-')
fh=-1,jp=getchar();
while (jp>='0'&&jp<='9')
out=out*10+jp-'0',jp=getchar();
return out*fh;
}
const int MAXN=1e5+10;
double x[MAXN],y[MAXN];
double sqr(double x)
{
double res=1.0*x*(x+1)*(2*x+1);
res/=6;
return res;
}
struct node
{
int l,r,siz;
double sumx,sumy,sumsq,sumpro;
bool tag_cover;
double tag_addx,tag_addy;
node()
{
tag_addx=0;
tag_addy=0;
tag_cover=false;
}
} Tree[MAXN<<2];
#define root Tree[o]
#define lson Tree[o<<1]
#define rson Tree[o<<1|1]
void pushup(int o)
{
root.sumx=lson.sumx+rson.sumx;
root.sumy=lson.sumy+rson.sumy;
root.sumsq=lson.sumsq+rson.sumsq;
root.sumpro=lson.sumpro+rson.sumpro;
}
void modifiy_addx(int o,double c)
{
root.sumsq+=root.siz*c*c+2*c*root.sumx;
root.sumpro+=c*root.sumy;
root.sumx+=root.siz*c;
root.tag_addx+=c;
}
void modifiy_addy(int o,double c)
{
root.sumpro+=c*root.sumx;
root.sumy+=root.siz*c;
root.tag_addy+=c;
}
void modifiy_cover(int o)
{
root.sumx=root.sumy=1LL*(root.l+root.r)*root.siz/2.0;
root.sumpro=root.sumsq=sqr(root.r)-sqr(root.l-1);
root.tag_addx=root.tag_addy=0;
root.tag_cover=true;
}
void pushdown(int o)
{
if(root.tag_cover)
{
modifiy_cover(o<<1);
modifiy_cover(o<<1|1);
root.tag_cover=false;
}
if(root.tag_addx)
{
modifiy_addx(o<<1,root.tag_addx);
modifiy_addx(o<<1|1,root.tag_addx);
root.tag_addx=0;
}
if(root.tag_addy)
{
modifiy_addy(o<<1,root.tag_addy);
modifiy_addy(o<<1|1,root.tag_addy);
root.tag_addy=0;
}
}
void BuildTree(int o,int l,int r)
{
root.l=l,root.r=r,root.siz=r-l+1;
if(l==r)
{
root.sumx=x[l];
root.sumy=y[l];
root.sumpro=x[l]*y[l];
root.sumsq=x[l]*x[l];
return;
}
int mid=(l+r)>>1;
BuildTree(o<<1,l,mid);
BuildTree(o<<1|1,mid+1,r);
pushup(o);
}
void update_addx(int o,int L,int R,double c)
{
int l=root.l,r=root.r;
if(l>R || L>r)
return;
if(L<=l && r<=R)
{
modifiy_addx(o,c);
return;
}
pushdown(o);
int mid=(l+r)>>1;
if(L<=mid)
update_addx(o<<1,L,R,c);
if(R>mid)
update_addx(o<<1|1,L,R,c);
pushup(o);
}
void update_addy(int o,int L,int R,double c)
{
int l=root.l,r=root.r;
if(l>R || L>r)
return;
if(L<=l && r<=R)
{
modifiy_addy(o,c);
return;
}
pushdown(o);
int mid=(l+r)>>1;
if(L<=mid)
update_addy(o<<1,L,R,c);
if(R>mid)
update_addy(o<<1|1,L,R,c);
pushup(o);
}
void update_cover(int o,int L,int R)
{
int l=root.l,r=root.r;
if(l>R || L>r)
return;
if(L<=l && r<=R)
{
modifiy_cover(o);
return;
}
pushdown(o);
int mid=(l+r)>>1;
if(L<=mid)
update_cover(o<<1,L,R);
if(R>mid)
update_cover(o<<1|1,L,R);
pushup(o);
}
double query_sumx(int o,int L,int R)
{
int l=root.l,r=root.r;
if(l>R || L>r)
return 0;
if(L<=l && r<=R)
return root.sumx;
double res=0;
pushdown(o);
int mid=(l+r)>>1;
if(L<=mid)
res+=query_sumx(o<<1,L,R);
if(R>mid)
res+=query_sumx(o<<1|1,L,R);
return res;
}
double query_sumy(int o,int L,int R)
{
int l=root.l,r=root.r;
if(l>R || L>r)
return 0;
if(L<=l && r<=R)
return root.sumy;
double res=0;
pushdown(o);
int mid=(l+r)>>1;
if(L<=mid)
res+=query_sumy(o<<1,L,R);
if(R>mid)
res+=query_sumy(o<<1|1,L,R);
return res;
}
double query_sumpro(int o,int L,int R)
{
int l=root.l,r=root.r;
if(l>R || L>r)
return 0;
if(L<=l && r<=R)
return root.sumpro;
double res=0;
pushdown(o);
int mid=(l+r)>>1;
if(L<=mid)
res+=query_sumpro(o<<1,L,R);
if(R>mid)
res+=query_sumpro(o<<1|1,L,R);
return res;
}
double query_sumsqr(int o,int L,int R)
{
int l=root.l,r=root.r;
if(l>R || L>r)
return 0;
if(L<=l && r<=R)
return root.sumsq;
double res=0;
pushdown(o);
int mid=(l+r)>>1;
if(L<=mid)
res+=query_sumsqr(o<<1,L,R);
if(R>mid)
res+=query_sumsqr(o<<1|1,L,R);
return res;
}
int n,m;
int main()
{
n=read(),m=read();
for(int i=1; i<=n; ++i)
scanf("%lf",&x[i]);
for(int i=1; i<=n; ++i)
scanf("%lf",&y[i]);
BuildTree(1,1,n);
double S,T;
while(m--)
{
int op=read();
if(op==1)
{
int L=read(),R=read();
double totx=query_sumx(1,L,R);
double toty=query_sumy(1,L,R);
double avrx=totx/(R-L+1);
double avry=toty/(R-L+1);
double ans=query_sumpro(1,L,R)+(R-L+1)*avrx*avry-toty*avrx-totx*avry;
ans/=query_sumsqr(1,L,R)+(R-L+1)*avrx*avrx-2*avrx*totx;
printf("%.10lf\n",ans);
}
else if(op==2)
{
int L=read(),R=read();
scanf("%lf%lf",&S,&T);
update_addx(1,L,R,S);
update_addy(1,L,R,T);
}
else
{
int L=read(),R=read();
scanf("%lf%lf",&S,&T);
update_cover(1,L,R);
update_addx(1,L,R,S);
update_addy(1,L,R,T);
}
}
return 0;
}

Loj 2005 相关分析的更多相关文章

  1. [loj#2005][SDOI2017]相关分析 _线段树

    「SDOI2017」相关分析 题目链接:https://loj.ac/problem/2005 题解: 把上面的式子拆掉,把下面的式子拆掉. 发现所有的东西都能用线段树暴力维护. 代码: #inclu ...

  2. LOJ #2005. 「SDOI2017」相关分析 线段树维护回归直线方程

    题目描述 \(Frank\) 对天文学非常感兴趣,他经常用望远镜看星星,同时记录下它们的信息,比如亮度.颜色等等,进而估算出星星的距离,半径等等. \(Frank\) 不仅喜欢观测,还喜欢分析观测到的 ...

  3. Loj #2321. 「清华集训 2017」无限之环

    Loj #2321. 「清华集训 2017」无限之环 曾经有一款流行的游戏,叫做 *Infinity Loop***,先来简单的介绍一下这个游戏: 游戏在一个 \(n \times m\) 的网格状棋 ...

  4. Loj #2731 「JOISC 2016 Day 1」棋盘游戏

    Loj 2731 「JOISC 2016 Day 1」棋盘游戏 JOI 君有一个棋盘,棋盘上有 \(N\) 行 \(3\) 列 的格子.JOI 君有若干棋子,并想用它们来玩一个游戏.初始状态棋盘上至少 ...

  5. SDOI2017相关分析 线段树

    题目 https://loj.ac/problem/2005 思路 \[ \sum_{L}^{R}{(x_i-x)^{2}} \] \[ \sum_{L}^{R}{(x_i^2-2*x_i*x+x^{ ...

  6. 【LOJ】#2886. 「APIO2015」巴厘岛的雕塑 Bali Sculptures

    题解 感觉自己通过刷水题混LOJ刷题量非常成功 首先是二进制枚举位,判是否合法 要写两个solve不是很开心,\(A\)不为1的直接记录状态\(f[i][j]\)为能否到达前\(i\)个分成\(j\) ...

  7. LOJ 2085: 洛谷 P1587: bzoj 4652: 「NOI2016」循环之美

    题目传送门:LOJ #2085. 两个月之前做的傻题,还是有必要补一下博客. 题意简述: 求分子为不超过 \(n\) 的正整数,分母为不超过 \(m\) 的正整数的所有互不相等的分数中,有多少在 \( ...

  8. 【LOJ】#3090. 「BJOI2019」勘破神机

    LOJ#3090. 「BJOI2019」勘破神机 为了这题我去学习了一下BM算法.. 很容易发现这2的地方是\(F_{1} = 1,F_{2} = 2\)的斐波那契数列 3的地方是\(G_{1} = ...

  9. 【LOJ】#3089. 「BJOI2019」奥术神杖

    LOJ#3089. 「BJOI2019」奥术神杖 看见乘积就取log,开根号就是除法,很容易发现这就是一道01分数规划.. 然后建出AC自动机直接dp就行,判断条件要设成>0,因为起点的值是1, ...

随机推荐

  1. "字节跳动杯"2018中国大学生程序设计竞赛-女生专场 Solution

    A - 口算训练 题意:询问 $[L, R]$区间内 的所有数的乘积是否是D的倍数 思路:考虑分解质因数 显然,一个数$x > \sqrt{x} 的质因子只有一个$ 那么我们考虑将小于$\sqr ...

  2. supervisor安装及其配置

    一.supervisor概述 supervisor是一个c/s系统,被用来在类Unix系统中监控进程状态.supervisor使用python开发. 服务端进程为supervisord,主要负责启动自 ...

  3. java压缩zip文件中文乱码问题

    用java来打包文件生成压缩文件,有两个地方会出现乱码 1.内容的中文乱码问题,这个问题网上很多人给出了解决方法,两种:修改sun的源码:使用开源的类库org.apache.tools.zip.Zip ...

  4. mysql 触发器 trigger用法 one (简单的)

    实例~~ example1: 创建表tab1 1 2 3 4 DROP TABLE IF EXISTS tab1; CREATE TABLE tab1(     tab1_id varchar(11) ...

  5. Python3.x:os.mkdir与 os.makedirs(创建目录方法)区别

    Python3.x:os.mkdir与 os.makedirs区别 1,os.mkdir mkdir( path [,mode] ) 说明: 创建一个目录,可以是相对或者绝对路径,mode的默认模式是 ...

  6. 20145105 《Java程序设计》第4周学习总结

    20145105 <Java程序设计>第4周学习总结 教材学习内容总结 第六章 继承与多态 一.何谓继承 (一)继承共同行为 继承基本上就是避免多个类间重复定义共同行为. 如:下述代码将剑 ...

  7. shell 变量赋值运算

    .变量赋值: name=lbg 等号前后不能有空格 name="Lebron James" 变量值中有空格要用双引号 echo ${name} 用${}更保险 shopt -s - ...

  8. 理解flex布局

    我们传统的布局方式是基于在盒子模型下的,依赖于display属性的,position属性的或者是float属性的,但是在传统的布局上面并不好布局; 比如我们想让某个元素垂直居中的话,我们常见的会让其元 ...

  9. Redis为什么要把所有数据放到内存中?

    Redis为了达到最快的读写速度将数据都读到内存中,并通过异步的方式将数据写入磁盘.所以Redis具有快速和数据持久化的特性. 如果不将数据放到内存中,磁盘的I/O速度会严重影响redis的性能.在内 ...

  10. voj 1754 spfa

    最优贸易 最优贸易 描述 C 国有 n 个大城市和 m 条道路,每条道路连接这 n 个城市中的某两个城市.任意两个 城市之间最多只有一条道路直接相连.这 m 条道路中有一部分为单向通行的道路,一部分 ...