• SDOI2017 相关分析


    把两个式子拆开

      Σ(xi-px)(yi-py) =Σ xiyi + py * Σ xi - px * Σ yi + Σ 1* px * py

      Σ (xi-px)² = Σ xi² +  px * Σ xi * 2  + Σ 1* px²

    用线段树维护 Σxiyi , Σxi ,Σ yi , Σ xi² 

    同时维护两个标记:增加和修改

    对于增加操作,假设给x增加a,给y增加b

    Σ (xi+a)(yi+b)= Σ xiyi + b * Σ xi + a * Σ yi + Σ 1*a*b

    Σ (xi + a )² =   Σ xi² + 2 * a * Σ xi + Σ 1 * a²

    Σ xi += Σ 1 * s 

    Σ yi += Σ 1 * t 

    对于修改操作,假设x修改为s+i,y修改为t+i

    Σ xiyi = Σ (s+i)(t+i)= Σ 1 * s * t + Σ  s * i + Σ t * i + Σ 1 * i² = Σ 1 * s * t + (s+t)* Σ i +  Σ 1 * i² 

    同理,Σ xi² = Σ 1 * s *s + s * 2 * Σ i +  Σ 1 * i²

    Σ xi = Σ 1 * s +Σ i

    Σ yi = Σ 1 * t +Σ i

    所以 线段树还需要维护 Σi ,Σ i²

    然后就是增加标记与修改标记的同时维护

    可参考codevs 线段树练习5 http://www.cnblogs.com/TheRoadToTheGold/p/6690565.html

    #include<cstdio>
    #define N 100001
    using namespace std;
    int n,m,opl,opr;
    double totx,toty,totxy,totxx;
    double px,py,ans,fz,fm;
    double x[N],y[N],s,t;
    struct node
    {
        int l,r,siz;
        double sumx,sumy,fx,fy,xx,xy;
        double tagx,tagy;
        bool v;
        double toti,toti2;
    }tr[N*4];
    void up(int k)
    {
        tr[k].sumx=tr[k<<1].sumx+tr[k<<1|1].sumx;
        tr[k].sumy=tr[k<<1].sumy+tr[k<<1|1].sumy;
        tr[k].xx=tr[k<<1].xx+tr[k<<1|1].xx;
        tr[k].xy=tr[k<<1].xy+tr[k<<1|1].xy;
        tr[k].toti=tr[k<<1].toti+tr[k<<1|1].toti;
        tr[k].toti2=tr[k<<1].toti2+tr[k<<1|1].toti2;
    }
    void down(int k)
    {
        tr[k<<1].xy+=tr[k].fy*tr[k<<1].sumx+tr[k].fx*tr[k<<1].sumy+tr[k].fx*tr[k].fy*tr[k<<1].siz;
        tr[k<<1|1].xy+=tr[k].fy*tr[k<<1|1].sumx+tr[k].fx*tr[k<<1|1].sumy+tr[k].fx*tr[k].fy*tr[k<<1|1].siz;
        tr[k<<1].xx+=tr[k].fx*tr[k<<1].sumx+tr[k].fx*tr[k<<1].sumx+tr[k].fx*tr[k].fx*tr[k<<1].siz;
        tr[k<<1|1].xx+=tr[k].fx*tr[k<<1|1].sumx+tr[k].fx*tr[k<<1|1].sumx+tr[k].fx*tr[k].fx*tr[k<<1|1].siz;
        tr[k<<1].sumx+=tr[k<<1].siz*tr[k].fx;
        tr[k<<1].sumy+=tr[k<<1].siz*tr[k].fy;
        tr[k<<1|1].sumx+=tr[k<<1|1].siz*tr[k].fx;
        tr[k<<1|1].sumy+=tr[k<<1|1].siz*tr[k].fy;
        tr[k<<1].fx+=tr[k].fx;
        tr[k<<1].fy+=tr[k].fy;
        tr[k<<1|1].fx+=tr[k].fx;
        tr[k<<1|1].fy+=tr[k].fy;
        tr[k].fx=tr[k].fy=0;
    }
    void down2(int k)
    {
        tr[k<<1].sumx=tr[k].tagx*tr[k<<1].siz+tr[k<<1].toti;
        tr[k<<1|1].sumx=tr[k].tagx*tr[k<<1|1].siz+tr[k<<1|1].toti;
        tr[k<<1].sumy=tr[k].tagy*tr[k<<1].siz+tr[k<<1].toti;
        tr[k<<1|1].sumy=tr[k].tagy*tr[k<<1|1].siz+tr[k<<1|1].toti;
        tr[k<<1].xy=tr[k].tagx*tr[k].tagy*tr[k<<1].siz+tr[k<<1].toti*(tr[k].tagx+tr[k].tagy)+tr[k<<1].toti2;
        tr[k<<1|1].xy=tr[k].tagx*tr[k].tagy*tr[k<<1|1].siz+tr[k<<1|1].toti*(tr[k].tagx+tr[k].tagy)+tr[k<<1|1].toti2;
        tr[k<<1].xx=tr[k].tagx*tr[k].tagx*tr[k<<1].siz+tr[k<<1].toti*tr[k].tagx*2+tr[k<<1].toti2;
        tr[k<<1|1].xx=tr[k].tagx*tr[k].tagx*tr[k<<1|1].siz+tr[k<<1|1].toti*tr[k].tagx*2+tr[k<<1|1].toti2;
        tr[k<<1].tagx=tr[k].tagx; 
        tr[k<<1|1].tagx=tr[k].tagx;
        tr[k<<1].tagy=tr[k].tagy;
        tr[k<<1|1].tagy=tr[k].tagy;
        tr[k<<1].v=tr[k<<1|1].v=true;
        tr[k].tagx=tr[k].tagy=tr[k].v=0;
        tr[k<<1].fx=tr[k<<1].fy=0;
        tr[k<<1|1].fx=tr[k<<1|1].fy=0;
    }
    void build(int k,int l,int r)
    {
        tr[k].l=l; tr[k].r=r;  tr[k].siz=r-l+1; 
        if(l==r)
        {
            tr[k].sumx=x[l];
            tr[k].sumy=y[l];
            tr[k].xx=x[l]*x[l];
            tr[k].xy=x[l]*y[l];
            tr[k].toti=l;
            tr[k].toti2=(double)l*l;
            return;
        }
        int mid=l+r>>1;
        build(k<<1,l,mid);
        build(k<<1|1,mid+1,r);
        up(k);
    }
    void query(int k)
    {
        if(tr[k].l>=opl&&tr[k].r<=opr)
        {
            totx+=tr[k].sumx;
            toty+=tr[k].sumy;
            totxy+=tr[k].xy;
            totxx+=tr[k].xx;
            return;
        }
        if(tr[k].v) down2(k);
        if(tr[k].fx||tr[k].fy) down(k);
        int mid=tr[k].l+tr[k].r>>1;
        if(opl<=mid) query(k<<1);
        if(opr>mid) query(k<<1|1);
    }
    void add(int k)
    {
        if(tr[k].l>=opl&&tr[k].r<=opr)
        {
            tr[k].xy+=t*tr[k].sumx+s*tr[k].sumy+s*t*tr[k].siz;
            tr[k].xx+=s*tr[k].sumx+s*tr[k].sumx+s*s*tr[k].siz;
            tr[k].sumx+=s*tr[k].siz;
            tr[k].sumy+=t*tr[k].siz;
            tr[k].fx+=s;
            tr[k].fy+=t;
            return;
        }
        if(tr[k].v) down2(k);
        if(tr[k].fx||tr[k].fy) down(k);
        int mid=tr[k].l+tr[k].r>>1;
        if(opl<=mid) add(k<<1);
        if(opr>mid) add(k<<1|1);
        up(k);
    }
    void change2(int k)
    {
        if(tr[k].l>=opl&&tr[k].r<=opr)
        {
            tr[k].fx=tr[k].fy=0;
            tr[k].tagx=s;tr[k].tagy=t;
            tr[k].v=true;
            tr[k].sumx=s*tr[k].siz+tr[k].toti;
            tr[k].sumy=t*tr[k].siz+tr[k].toti;
            tr[k].xy=s*t*tr[k].siz+tr[k].toti*(s+t)+tr[k].toti2;
            tr[k].xx=s*s*tr[k].siz+tr[k].toti*s*2+tr[k].toti2;
            return;
        }
        if(tr[k].v) down2(k);
        if(tr[k].fx||tr[k].fy) down(k);
        int mid=tr[k].l+tr[k].r>>1;
        if(opl<=mid) change2(k<<1);
        if(opr>mid) change2(k<<1|1);
        up(k);
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++) scanf("%lf",&x[i]);
        for(int i=1;i<=n;i++) scanf("%lf",&y[i]);
        build(1,1,n);
        int z,u;
        while(m--)
        {
            scanf("%d",&z);
            if(z==1)
            {
                scanf("%d%d",&opl,&opr);
                u=opr-opl+1;
                totx=0;    toty=0; totxy=0; totxx=0;
                query(1);
                px=totx/u;
                py=toty/u;
                fz=totxy-totx*py-px*toty+px*py*u;
                fm=totxx-totx*px*2+px*px*u;
                ans=fz/fm;
                printf("%.10lf
    ",ans);
            }
            else if(z==2)
            {
                scanf("%d%d",&opl,&opr);
                scanf("%lf%lf",&s,&t);
                add(1);
            }
            else
            {
                scanf("%d%d",&opl,&opr);
                scanf("%lf%lf",&s,&t);
                change2(1);
            }
        }
        return 0;
    }
  • 相关阅读:
    2019/10/9 CSP-S 模拟测
    简单的面向对象
    魔术变量
    函数
    全局变量
    超级全局变量
    for循环
    while循环
    php数组排序
    python打造XslGenerator
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/6701784.html
Copyright © 2020-2023  润新知