您的位置:首页 > 其它

SDOI2017 相关分析

2017-04-12 22:32 337 查看




把两个式子拆开

Σ(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
,y
,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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: