【IOI2000】邮局
我不想打表,所以我证明了这道题的四边形不等式。
这个不难,若
若
中位数向左发生偏移是类似的。
因此
下面
对于
那么有
证毕。
之后就是一些常规操作了。
对于
对于
两式相加,有
减掉重的部分,有
以此类推,有
之后就是推
证明
设
还有
四边形不等式,
有
因此
之后数学归纳法即可,已经比打表法好多!。
之后证明一下决策单调性
简记
证明:
-
记
p=p_{i,j} ,那么对于\forall k\le p ,因为f 满足四边形不等式,则有f_{p,j-1}+f_{k,j}\ge f_{k,j-1}+f_{p,j} f_{k,j}-f_{p,j}\ge f_{k,j-1}-f_{p,j-1} -
因为
p 的最优性,那么f_{k,j-1}+w_{k+1,i}\ge f_{p,j-1}+w_{p+1,i} -
因此
(f_{k,j}+w_{k+1,i})-(f_{p,j}+w_{p+1,i})=f_{k,j}+w_{k+1,i}-f_{p,j}-w_{p+1,i}\ge f_{k,j-1}-f_{p,j-1}+w_{k+1,i}-w_{p+1,i}\ge 0 因此
f_{k,j}+w_{k+1,i}\ge f_{p,j}+w_{p+1,i} 所以对于
f_{i,j} 来说,p 优于任何的k\le p 。因此p_{i,j}\ge p_{i,j-1} 同理,
p_{i,j}\le p_{i+1,j}
证毕。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#define gc getchar()
using namespace std;
const int P=305,N=3005;
inline void qr(int &x)
{
x=0;char c=gc;int f=1;
while(c<'0'||c>'9'){if(c=='-')f=-1;c=gc;}
while(c>='0'&&c<='9'){x=x*10+(c^48);c=gc;}
x*=f;
}
void qw(int x)
{
if(x<0)x=-x,putchar('-');
if(x/10)qw(x/10);
putchar(x%10+48);
}
int f[N][P],s[N],a[N],p[N][P];
inline int calc(int l,int r)
{
int mid=l+r+1>>1;
return a[mid]*(mid-l+1)-(s[mid]-s[l-1])+(s[r]-s[mid])-a[mid]*(r-mid);
}
int main()
{
int n,m;qr(n),qr(m);
for(int i=1;i<=n;i++)qr(a[i]),s[i]=s[i-1]+a[i];
memset(f,0x3f,sizeof(f));
for(int i=1;i<=n;i++)f[i][1]=calc(1,i);
for(int i=1;i<=m;i++)p[n][i]=1;
for(int j=2;j<=m;j++)
{
p[n+1][j]=n;int tmp=0x3f3f3f3f;
for(int i=n;i>=1;i--)
for(int k=p[i][j-1];k<=p[i+1][j];k++)
if((tmp=f[k][j-1]+calc(k+1,i))<f[i][j])
{
f[i][j]=tmp;
p[i][j]=k;
}
}
qw(f[n][m]);puts("");
return 0;
}