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个间隔,一定是均分更优。设
s[i]−s[i−1]=d,(d−l)2=d2+l2−2∗d∗l
设∑a[i]=d
l^2为定值,2*l*
∑a[i]=2∗l∗d为定值,所以我们只用讨论∑a[i]2
由柯西不等式
k∗∑a[i]2>=(∑a[i])2=d2
我们发现分成k份后的贡献为 k∗(d/k−l)2=d2/k+k∗l2−2∗d∗l 当k增加1时,答案的增量为 l2−d2k∗(k+1) 这时我们就想到了70%的nlogn的做法,即每次从set中取出 l2−d2k∗(k+1) 的最小值。
我们还可以证明,对于一个间隔,分在它的区间至少为 ⌊|s[i]−s[i−1]|∗m∑|s[i]−s[i−1]|⌋ 我们来证明一下:
设 ∑|s[i]−s[i−1]|=sum
对于一个i,若存在一个最优值满足分于i的区间为 ⌊|s[i]−s[i−1]|∗m∑|s[i]−s[i−1]|⌋−1 ,另一个j的分于j的区间即为 ⌊|s[j]−s[j−1]|∗m∑|s[i]−s[i−1]|⌋+1 ,那么我们现在若可以在i或j改变一个区间
−di2(⌊|di|∗msum⌋−1)∗(⌊|di|∗msum⌋)<=−di2(⌊|di|∗msum⌋)2=−sum2m2
−dj2(⌊|dj|∗msum⌋+1)∗(⌊|dj|∗msum⌋+2)>=−dj2(⌊|dj|∗msum⌋)2=−sum2m2
明显增加i更优。
所以我们可以事先给每个区间 ⌊|s[i]−s[i−1]|∗msum⌋ 的区间,同时我们还可以由增量 l2−d2k∗(k+1) 算出区间也至少为 ⌊l/d⌋ ,两者取min,然后继续执行70分算法。每个区间改变量不超过1。时间复杂度O(NlogN)。
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);
}