洛谷P3707 [SDOI2017]相关分析

题目描述

Frank对天文学非常感兴趣,他经常用望远镜看星星,同时记录下它们的信息,比如亮度、颜色等等,进而估算出星星的距离,半径等等。

Frank不仅喜欢观测,还喜欢分析观测到的数据。他经常分析两个参数之间(比如亮度和半径)是否存在某种关系。

现在Frank要分析参数XX 与YY 之间的关系。他有nn 组观测数据,第ii 组观测数据记录了x_ixi? 和y_iyi? 。他需要一下几种操作

  • 1 L,RL,R :

用直线拟合第LL 组到底RR 组观测数据。用\overline{x}x 表示这些观测数据中xx 的平均数,用\overline{y}y? 表示这些观测数据中yy 的平均数,即

\overline{x}={1 \over R-L+1} \sum _{i=L} ^R x_ix=R−L+11?∑i=LR?xi?

\overline{y}={1 \over R-L+1} \sum _{i=L} ^R y_iy?=R−L+11?∑i=LR?yi?

如果直线方程是y=ax+by=ax+b ,那么a,ba,b 应当这样计算:

a={\sum_{i=L} ^R (x_i-\overline{x})(y_i-\overline{y}) \over \sum _{i=L} ^R (x_i -\overline{x})^2}a=∑i=LR?(xi?−x)2∑i=LR?(xi?−x)(yi?−y?)?

你需要帮助Frank计算aa 。

  • 2 L,R,S,TL,R,S,T :

Frank发现测量数据第LL 组到底RR 组数据有误差,对每个ii 满足L \leq i \leq RL≤i≤R ,x_ixi? 需要加上SS ,y_iyi? 需要加上TT 。

  • 3 L,R,S,TL,R,S,T :

Frank发现第LL 组到第RR 组数据需要修改,对于每个ii 满足L \leq i \leq RL≤i≤R ,x_ixi? 需要修改为(S+i)(S+i) ,y_iyi? 需要修改为(T+i)(T+i)。

输入输出格式

输入格式:

第一行两个数n,mn,m ,表示观测数据组数和操作次数。

接下来一行nn 个数,第ii 个数是x_ixi? 。

接下来一行nn 个数,第ii 个数是y_iyi? 。

接下来mm 行,表示操作,格式见题目描述。

输出格式:

对于每个1操作,输出一行,表示直线斜率aa 。选手输出与标准输出的绝对误差或相对误差不超过10^{-5}10−5 即为正确。

输入输出样例

输入样例#1: 复制

3 5
1 2 3
1 2 3
1 1 3
2 2 3 -3 2
1 1 2
3 1 2 2 1
1 1 3

输出样例#1: 复制

1.0000000000
-1.5000000000
-0.6153846154

说明

对于20%的数据 1 \leq n,m \leq 10001≤n,m≤1000

另有20%的数据,没有3操作,且2操作中S=0S=0

另有30%的数据,没有3操作。

对于100%的数据,1 \leq n,m \leq 10^5,0 \leq |S|,|T| \leq 10^5,0 \leq |x_i|,|y_i| \leq 10^51≤n,m≤105,0≤∣S∣,∣T∣≤105,0≤∣xi?∣,∣yi?∣≤105

保证1操作不会出现分母为00 的情况。

时间限制:1s

空间限制:128MB

考场上:

线段树裸题—>100

wtf?为什么会有类似等差数列的东西?—>70

maya..被卡精度了QWQ—>40

思路很简单,把式子拆开,然后你就会发现只需要维护$x_i*y_i,x_i,y_i,x^2$的和

具体怎么维护懒得打了(麻烦。)

建议看这里的第一篇题解

https://www.luogu.org/problemnew/solution/P3707

// luogu-judger-enable-o2
#include<cstdio>
#include<queue>
#include<cstring>
#define int long long
#define ls k<<1
#define rs k<<1|1
#define INF 1e8+10
using namespace std;
const int MAXN=1e6+10;
//#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,MAXN,stdin),p1==p2)?EOF:*p1++)
inline int read()
{
    char c=getchar();int x=0,f=1;
    while(c<‘0‘||c>‘9‘){if(c==‘-‘)f=-1;c=getchar();}
    while(c>=‘0‘&&c<=‘9‘){x=x*10+c-‘0‘;c=getchar();}
    return x*f;
}
struct node
{
    int l,r,siz;
    double po;//x^2
    double mul;//xi*yi
    double sx,sy;//sigma
    double ax,ay;//add
    bool lazy;//memset
    node(){sx=-43800000;sy=-43800000;}
}T[MAXN];
struct Ans
{
    double sxiyi;
    double sxi,syi;
    double pox;
    Ans(){sxiyi=sxi=syi=pox=0;}
};
Ans GetAns(int k)
{
    Ans rt;
    rt.sxiyi=T[k].mul;
    rt.sxi=T[k].sx;
    rt.syi=T[k].sy;
    rt.pox=T[k].po;
    return rt;
}
void update(int k)
{
    T[k].po=T[ls].po+T[rs].po;
    T[k].mul=T[ls].mul+T[rs].mul;
    T[k].sx=T[ls].sx+T[rs].sx;
    T[k].sy=T[ls].sy+T[rs].sy;
}
void Memset(int k)
{
    T[k].sx=(T[k].siz*(T[k].l+T[k].r))>>1;
    T[k].sy=(T[k].siz*(T[k].l+T[k].r))>>1;
    T[k].mul=(T[k].r*(T[k].r+1)*(2*T[k].r+1))/6-(T[k].l*(T[k].l-1)*(2*T[k].l-1))/6;
    T[k].po=(T[k].r*(T[k].r+1)*(2*T[k].r+1))/6-(T[k].l*(T[k].l-1)*(2*T[k].l-1))/6;
    T[k].ax=T[k].ay=0;
    T[k].lazy=1;
}
void Clear(int k,int S,int TT)
{
    T[k].po=T[k].po + 2.0*S*T[k].sx + T[k].siz*S*S;
    T[k].mul=T[k].mul + TT*T[k].sx + S*T[k].sy + T[k].siz*S*TT;
    T[k].sx=T[k].sx + T[k].siz*S;
    T[k].sy=T[k].sy + T[k].siz*TT;
    T[k].ax+=S;
    T[k].ay+=TT;
}
void pushdown(int k)
{
    if(T[k].lazy)
    {
        Memset(ls);
        Memset(rs);
        T[k].lazy=0;
        return ;
    }
    int S=T[k].ax,TT=T[k].ay;
    Clear(ls,S,TT);
    Clear(rs,S,TT);
    T[k].ax=0;
    T[k].ay=0;
}
void Build(int ll,int rr,int k)
{
    T[k].l=ll;T[k].r=rr;
    T[k].siz=rr-ll+1;
    if(ll==rr)
    {
        if(T[k].sx==-43800000) {T[k].sx=read();return ;}
        T[k].sy=read();
        T[k].po=T[k].sx*T[k].sx;
        T[k].mul=T[k].sx*T[k].sy;
        return ;
    }
    int mid=ll+rr>>1;
    Build(ll,mid,ls);
    Build(mid+1,rr,rs);
    update(k);
}
Ans Query(int k,int ll,int rr)
{
    pushdown(k);
    Ans rt;
    if(ll<=T[k].l&&T[k].r<=rr)
    {
        rt=GetAns(k);
        return rt;
    }
    pushdown(k);
    int mid=T[k].l+T[k].r>>1;
    if(ll<=mid)
    {
        pushdown(ls);
        Ans Q=Query(ls,ll,rr);
        rt.sxiyi+=Q.sxiyi;
        rt.sxi+=Q.sxi;
        rt.syi+=Q.syi;
        rt.pox+=Q.pox;
    }
    if(rr>mid)
    {
        pushdown(rs);
        Ans Q=Query(rs,ll,rr);
        rt.sxiyi+=Q.sxiyi;
        rt.sxi+=Q.sxi;
        rt.syi+=Q.syi;
        rt.pox+=Q.pox;
    }
    return rt;
}
void IntervalAdd(int k,int ll,int rr,int S,int TT)
{
    pushdown(k);
    if(ll<=T[k].l&&T[k].r<=rr)
    {
        Clear(k,S,TT);
        return ;
    }
    pushdown(k);
    int mid=T[k].l+T[k].r>>1;
    if(ll<=mid) pushdown(ls),IntervalAdd(ls,ll,rr,S,TT);
    if(rr>mid)  pushdown(rs),IntervalAdd(rs,ll,rr,S,TT);
    update(k);
}
void IntervalMemset(int k,int ll,int rr)
{
    pushdown(k);
    if(ll<=T[k].l&&T[k].r<=rr)
    {
        Memset(k);
        return ;
    }
    pushdown(k);
    int mid=T[k].l+T[k].r>>1;
    if(ll<=mid) pushdown(ls),IntervalMemset(ls,ll,rr);
    if(rr>mid)    pushdown(rs),IntervalMemset(rs,ll,rr);
    update(k);
}
main()
{
    #ifdef WIN32
    freopen("a.in","r",stdin);
    //freopen("c.out","w",stdout);
    #else
    #endif
    int N=read(),M=read();
    Build(1,N,1);
    Build(1,N,1);
    while(M--)
    {
        int opt=read();
        if(opt==1)
        {
            int L=read(),R=read();
            Ans ans=Query(1,L,R);
            double xba=(double)ans.sxi/(double)(R-L+1);
            double yba=(double)ans.syi/(double)(R-L+1);
            double up=ans.sxiyi-(double)yba*ans.sxi-(double)xba*ans.syi + (double)xba*yba*(R-L+1);
            double down=ans.pox - (double)2.0*xba*ans.sxi + (double)xba*xba*(R-L+1);
            printf("%.10lf\n",up/down);
        }
        else if(opt==2)
        {
            int L=read(),R=read(),S=read(),TT=read();
            IntervalAdd(1,L,R,S,TT);
        }
        else if(opt==3)
        {
            int L=read(),R=read(),S=read(),TT=read();
            IntervalMemset(1,L,R);
            IntervalAdd(1,L,R,S,TT);
        }
    }
    return 0;
}

稍微整理了一下

#include<cstdio>
#include<queue>
#include<cstring>
#define int long long
#define ls k<<1
#define rs k<<1|1
#define INF 1e8+10
using namespace std;
const int MAXN=1e6+10;
//#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,MAXN,stdin),p1==p2)?EOF:*p1++)
inline int read()
{
    char c=getchar();int x=0,f=1;
    while(c<‘0‘||c>‘9‘){if(c==‘-‘)f=-1;c=getchar();}
    while(c>=‘0‘&&c<=‘9‘){x=x*10+c-‘0‘;c=getchar();}
    return x*f;
}
struct node
{
    int l,r,siz;
    double po;//x^2
    double mul;//xi*yi
    double sx,sy;//sigma
    double ax,ay;//add
    bool lazy;//memset
    node(){sx=-43800000;sy=-43800000;}
}T[MAXN];
struct Ans
{
    double sxiyi;
    double sxi,syi;
    double pox;
    Ans(){sxiyi=sxi=syi=pox=0;}
};
Ans GetAns(int k)
{
    Ans rt;
    rt.sxiyi=T[k].mul;
    rt.sxi=T[k].sx;
    rt.syi=T[k].sy;
    rt.pox=T[k].po;
    return rt;
}
void update(int k)
{
    T[k].po=T[ls].po+T[rs].po;
    T[k].mul=T[ls].mul+T[rs].mul;
    T[k].sx=T[ls].sx+T[rs].sx;
    T[k].sy=T[ls].sy+T[rs].sy;
}
void pushdown(int k)
{
    if(T[k].lazy)
    {
        T[ls].sx=(T[ls].siz*(T[ls].l+T[ls].r))>>1;
        T[ls].sy=(T[ls].siz*(T[ls].l+T[ls].r))>>1;
        T[ls].mul=(T[ls].r*(T[ls].r+1)*(2*T[ls].r+1))/6-(T[ls].l*(T[ls].l-1)*(2*T[ls].l-1))/6;
        T[ls].po=(T[ls].r*(T[ls].r+1)*(2*T[ls].r+1))/6-(T[ls].l*(T[ls].l-1)*(2*T[ls].l-1))/6;
        T[ls].ax=T[ls].ay=0;
        T[ls].lazy=1;
        T[rs].sx=(T[rs].siz*(T[rs].l+T[rs].r))>>1;
        T[rs].sy=(T[rs].siz*(T[rs].l+T[rs].r))>>1;
        T[rs].mul=(T[rs].r*(T[rs].r+1)*(2*T[rs].r+1))/6-(T[rs].l*(T[rs].l-1)*(2*T[rs].l-1))/6;
        T[rs].po=(T[rs].r*(T[rs].r+1)*(2*T[rs].r+1))/6-(T[rs].l*(T[rs].l-1)*(2*T[rs].l-1))/6;
        T[rs].ax=T[rs].ay=0;
        T[rs].lazy=1;
        T[k].lazy=0;
        return ;
    }
    int S=T[k].ax,TT=T[k].ay;
    T[ls].po=T[ls].po+ 2.0*S*T[ls].sx + T[ls].siz*S*S;
    T[ls].mul=T[ls].mul + TT*T[ls].sx + S*T[ls].sy + T[ls].siz*S*TT;
    T[ls].sx=T[ls].sx + T[ls].siz*S;
    T[ls].sy=T[ls].sy + T[ls].siz*TT;
    T[ls].ax+=S;
    T[ls].ay+=TT;
    T[rs].po=T[rs].po+ 2.0*S*T[rs].sx + T[rs].siz*S*S;
    T[rs].mul=T[rs].mul + TT*T[rs].sx + S*T[rs].sy + T[rs].siz*S*TT;
    T[rs].sx=T[rs].sx + T[rs].siz*S;
    T[rs].sy=T[rs].sy + T[rs].siz*TT;
    T[rs].ax+=S;
    T[rs].ay+=TT;
    T[k].ax=0;
    T[k].ay=0;
}
void Build(int ll,int rr,int k)
{
    T[k].l=ll;T[k].r=rr;
    T[k].siz=rr-ll+1;
    if(ll==rr)
    {
        if(T[k].sx==-43800000) {T[k].sx=read();return ;}
        T[k].sy=read();
        T[k].po=T[k].sx*T[k].sx;
        T[k].mul=T[k].sx*T[k].sy;
        return ;
    }
    int mid=ll+rr>>1;
    Build(ll,mid,ls);
    Build(mid+1,rr,rs);
    update(k);
}
Ans Query(int k,int ll,int rr)
{
    pushdown(k);
    Ans rt;
    if(ll<=T[k].l&&T[k].r<=rr)
    {
        rt=GetAns(k);
        return rt;
    }
    pushdown(k);
    int mid=T[k].l+T[k].r>>1;
    if(ll<=mid)
    {
        pushdown(ls);
        Ans Q=Query(ls,ll,rr);
        rt.sxiyi+=Q.sxiyi;
        rt.sxi+=Q.sxi;
        rt.syi+=Q.syi;
        rt.pox+=Q.pox;
    }
    if(rr>mid)
    {
        pushdown(rs);
        Ans Q=Query(rs,ll,rr);
        rt.sxiyi+=Q.sxiyi;
        rt.sxi+=Q.sxi;
        rt.syi+=Q.syi;
        rt.pox+=Q.pox;
    }
    return rt;
}
void IntervalAdd(int k,int ll,int rr,int S,int TT)
{
    pushdown(k);
    if(ll<=T[k].l&&T[k].r<=rr)
    {
        T[k].po=T[k].po + 2.0*S*T[k].sx + T[k].siz*S*S;
        T[k].mul=T[k].mul + TT*T[k].sx + S*T[k].sy + T[k].siz*S*TT;
        T[k].sx=T[k].sx + T[k].siz*S;
        T[k].sy=T[k].sy + T[k].siz*TT;
        T[k].ax+=S;
        T[k].ay+=TT;
        return ;
    }
    pushdown(k);
    int mid=T[k].l+T[k].r>>1;
    if(ll<=mid) pushdown(ls),IntervalAdd(ls,ll,rr,S,TT);
    if(rr>mid)  pushdown(rs),IntervalAdd(rs,ll,rr,S,TT);
    update(k);
}
void IntervalMemset(int k,int ll,int rr)
{
    pushdown(k);
    if(ll<=T[k].l&&T[k].r<=rr)
    {
        T[k].sx=(T[k].siz*(T[k].l+T[k].r))>>1;
        T[k].sy=(T[k].siz*(T[k].l+T[k].r))>>1;
        T[k].mul=(T[k].r*(T[k].r+1)*(2*T[k].r+1))/6-(T[k].l*(T[k].l-1)*(2*T[k].l-1))/6;
        T[k].po=(T[k].r*(T[k].r+1)*(2*T[k].r+1))/6-(T[k].l*(T[k].l-1)*(2*T[k].l-1))/6;
        T[k].ax=T[k].ay=0;
        T[k].lazy=1;
        return ;
    }
    pushdown(k);
    int mid=T[k].l+T[k].r>>1;
    if(ll<=mid) pushdown(ls),IntervalMemset(ls,ll,rr);
    if(rr>mid)    pushdown(rs),IntervalMemset(rs,ll,rr);
    update(k);
}
main()
{
    #ifdef WIN32
    freopen("a.in","r",stdin);
    freopen("c.out","w",stdout);
    #else
    #endif
    int N=read(),M=read();
    Build(1,N,1);
    Build(1,N,1);
    while(M--)
    {
        int opt=read();
        if(opt==1)
        {
            int L=read(),R=read();
            Ans ans=Query(1,L,R);
            double xba=(double)ans.sxi/(double)(R-L+1);
            double yba=(double)ans.syi/(double)(R-L+1);
            double up=ans.sxiyi-(double)yba*ans.sxi-(double)xba*ans.syi + (double)xba*yba*(R-L+1);
            double down=ans.pox - (double)2.0*xba*ans.sxi + (double)xba*xba*(R-L+1);
            printf("%.10lf\n",up/down);
        }
        else if(opt==2)
        {
            int L=read(),R=read(),S=read(),TT=read();
            IntervalAdd(1,L,R,S,TT);
        }
        else if(opt==3)
        {
            int L=read(),R=read(),S=read(),TT=read();
            IntervalMemset(1,L,R);
            IntervalAdd(1,L,R,S,TT);
        }
    }
    return 0;
}

原文地址:https://www.cnblogs.com/zwfymqz/p/8502819.html

时间: 2024-10-06 16:03:39

洛谷P3707 [SDOI2017]相关分析的相关文章

luogu P3707 [SDOI2017]相关分析

传送门 对于题目要求的东西,考虑拆开懒得拆了 ,可以发现有\(\sum x\sum y\sum x^2\sum xy\)四个变量影响最终结果,考虑维护这些值 下面记\(l,r\)为区间两端点 首先是区间加操作,可以这样维护\[\sum(x+s)=\sum x+(r-l+1)s\]\[\sum(y+s)=\sum y+(r-l+1)s\]\[\sum(x+s)^2=\sum x^2+2s\sum x+(r-l+1)s^2\]\[\sum(x+s)(y+t)=\sum xy+s\sum y+t\su

洛谷 P2709 BZOJ 3781 小B的询问

题目描述 小B有一个序列,包含N个1~K之间的整数.他一共有M个询问,每个询问给定一个区间[L..R],求Sigma(c(i)^2)的值,其中i的值从1到K,其中c(i)表示数字i在[L..R]中的重复次数.小B请你帮助他回答询问. 输入输出格式 输入格式: 第一行,三个整数N.M.K. 第二行,N个整数,表示小B的序列. 接下来的M行,每行两个整数L.R. 输出格式: M行,每行一个整数,其中第i行的整数表示第i个询问的答案. 输入输出样例 输入样例#1: 6 4 3 1 3 2 1 1 3

洛谷1231 教辅的组成

洛谷1231 教辅的组成 https://www.luogu.org/problem/show?pid=1231 题目背景 滚粗了的HansBug在收拾旧语文书,然而他发现了什么奇妙的东西. 题目描述 蒟蒻HansBug在一本语文书里面发现了一本答案,然而他却明明记得这书应该还包含一份练习题.然而出现在他眼前的书多得数不胜数,其中有书,有答案,有练习册.已知一个完整的书册均应该包含且仅包含一本书.一本练习册和一份答案,然而现在全都乱做了一团.许多书上面的字迹都已经模糊了,然而HansBug还是可

洛谷教主花园dp

洛谷-教主的花园-动态规划 题目描述 教主有着一个环形的花园,他想在花园周围均匀地种上n棵树,但是教主花园的土壤很特别,每个位置适合种的树都不一样,一些树可能会因为不适合这个位置的土壤而损失观赏价值. 教主最喜欢3种树,这3种树的高度分别为10,20,30.教主希望这一圈树种得有层次感,所以任何一个位置的树要比它相邻的两棵树的高度都高或者都低,并且在此条件下,教主想要你设计出一套方案,使得观赏价值之和最高. 输入输出格式 输入格式: 输入文件garden.in的第1行为一个正整数n,表示需要种的

洛谷 P2801 教主的魔法 题解

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置. 题目链接:https://www.luogu.org/problem/show?pid=2801 题目描述 教主最近学会了一种神奇的魔法,能够使人长高.于是他准备演示给XMYZ信息组每个英雄看.于是N个英雄们又一次聚集在了一起,这次他们排成了一列,被编号为1.2.…….N. 每个人的身高一开始都是不超过1000的正整数.教主的魔法每次可以把闭区间[L, R](1≤L≤R≤N)内的英雄的身高全部加上一个整数W.(虽然L=R时并不

洛谷P1466 集合 Subset Sums

洛谷P1466 集合 Subset Sums这题可以看成是背包问题 用空间为 1--n 的物品恰好填充总空间一半的空间 有几种方案 01 背包问题 1.注意因为两个交换一下算同一种方案,所以最终 要 f [ v ] / 2 2.要开 long long 1 #include <cstdio> 2 #include <cstdlib> 3 #include <cmath> 4 #include <cstring> 5 #include <string&g

洛谷P1160 队列安排 链表

洛谷P1160 队列安排   链表 1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 #include <cstdlib> 5 #include <string> 6 #include <algorithm> 7 #include <iomanip> 8 #include <iostream> 9 using namespace std

洛谷 P3367 并查集模板

#include<cstdio> using namespace std; int n,m,p; int father[2000001]; int find(int x) { if(father[x]!=x) father[x]=find(father[x]); return father[x]; } void unionn(int i,int j) { father[j]=i; } int main() { scanf("%d%d",&n,&m); for

[题解]洛谷比赛『期末考后的休闲比赛2』

[前言] 这场比赛已经结束了有几天,但我各种忙,虽然AK但还是没来得及写题解.(我才不会告诉你我跑去学数据结构了) T1 区间方差 (就不贴题好了) 首先可以推公式(我们可以知道,线段树然而并不能通过初中学过的方差公式在log(L)内求出方差): (s2表示方差,L表示区间长度,xi表示区间的每一项,最后一个x上画了一根线表示这些数据的平均数) 用二项式定理完全平方公式可得: 再次展开: 另外,再代入以下这个 得到了: 然后继续吧.. 然后duang地一声合并同类项,于是我们得到了: 然后可以高