Description
Data Constraint
对于30%的数据,满足n<=500,m<=200
对于70%的数据,满足n<=20000,m<=100000
对于100%的数据,满足
1<=n<=50000,1<=m<=100000000,-100<=L<=100,|si|<=100
对于每个部分,均有50%的数据满足L=0
Solution
我们发现对于一个间距若分成k个间隔,一定是均分更优。设
由柯西不等式
我们发现分成k份后的贡献为
我们还可以证明,对于一个间隔,分在它的区间至少为
设
对于一个i,若存在一个最优值满足分于i的区间为
明显增加i更优。
所以我们可以事先给每个区间
Code
#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define db double
#include<set>
#define ll long long
using namespace std;
const int maxn=5e4+5;
ll d[maxn];
ll n,m,i,l,j;
db t,k,p,a[maxn],q,ans,x,y,z;
struct code{
db x;
int y,z;
bool friend operator < (code x,code y){
return x.x<y.x || x.x==y.x && x.y<y.y;
}
}g;
set<code>f;
db sqr(db x){return x*x;}
int main(){
freopen("seiran.in","r",stdin);freopen("seiran.out","w",stdout);
scanf("%d%d%lf",&n,&m,&p);
for (i=1;i<=n;i++)scanf("%lf",&a[i]),q+=abs(a[i]-a[i-1]);q-=abs(a[1]);
for (i=2;i<=n;i++){
x=abs(a[i]-a[i-1]);
if (p)d[i]=min(x/abs(p),x/q*m);
else d[i]=x/q*m;
if (!d[i])d[i]++;
ans+=d[i]*sqr((a[i]-a[i-1])/d[i]-p);g.z=2;
if (p*p-x*x/((d[i]+1)*d[i])<0)g.x=p*p-x*x/((d[i]+1)*d[i]),g.z=1;
else if (d[i]>1)g.x=-(p*p-x*x/((d[i]-1)*d[i])),g.z=-1;
if (g.z!=2)g.y=i,f.insert(g);
}
for (i=2;i<=n;i++)
m-=d[i]-1;
while (m){
g=*f.begin();
if (g.x>=0) break;
t++;
ans+=g.x;m-=g.z;
f.erase(g);x=a[g.y]-a[g.y-1];d[g.y]+=g.z;
if (g.z<0 && d[g.y]==1) continue;
g.x=g.z*(p*p-x*x/((d[g.y]+g.z)*d[g.y]));
f.insert(g);
}
if (ans<0) ans=0;
printf("%.3lf\n",ans);
}