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

SDOI2017 相关分析

时间:2017-04-12 22:58:37      阅读:344      评论:0      收藏:0      [点我收藏+]

标签:space   ret   cst   blog   node   get   blank   --   define   

技术分享技术分享

把两个式子拆开

  Σ(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\n",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;
}

 

SDOI2017 相关分析

标签:space   ret   cst   blog   node   get   blank   --   define   

原文地址:http://www.cnblogs.com/TheRoadToTheGold/p/6701784.html

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