码迷,mamicode.com
首页 > 其他好文 > 详细

Loj 2005 相关分析

时间:2019-03-28 13:48:55      阅读:94      评论:0      收藏:0      [点我收藏+]

标签:tps   roo   main   c++   get   end   for   nod   build   

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 相关分析

标签:tps   roo   main   c++   get   end   for   nod   build   

原文地址:https://www.cnblogs.com/jklover/p/10614239.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!