任务
解法
我们考虑将每双鞋按两鞋的中点排序,然后把鞋子放的就是一段连续的区间了。
现在我们设f[i][j]表示前i双鞋子,用了
fi,j=mink<i{fk,j−1+w(k+1,i)}
其中w(k+1,i)表示把第k+1到i双鞋放在一个鞋柜中的最小代价。
显然我们要求
知道了分布情况之后,我们再主席树中,找出中位数位置;
知道鞋柜位置之后,然后我们就再利用主席数,统计每只鞋子到这个位置的距离和。
这样的时间复杂度为
如果我们先枚举j,再枚举
那么我们就可以利用决策单调性来维护。
我这里采用的是分治法:
先算出fmid,i的决策点kmid,那么对于左右区间而言,枚举的决策点就可以减少了。
总的时间复杂度为O(nk∗log2)
代码
#include<iostream>
#include<algorithm>
#include<math.h>
#include<stdio.h>
#include<string.h>
#define ll long long
#define fo(i,x,y) for(ll i=x;i<=y;i++)
#define f(x,y) f[(x)*(m+1)+(y)]
using namespace std;
const char* fin="shoes.in";
const char* fout="shoes.out";
const ll inf=0x7fffffff;
const ll maxn=200007,maxt=maxn*60;
ll n,m,f[maxn],num,last,rt[maxn],ans,lim;
struct shoes{
ll x,y;
}a[maxn];
bool cmp(shoes a,shoes b){return (a.x+a.y)/2.0<(b.x+b.y)/2.0;}
struct node{
ll x,l,r,lson,rson;
}c[maxt];
void modify(ll l,ll r,ll t,ll v,ll _t){
ll mid=(l+r)/2;
if (l==r){
c[t].x=c[_t].x+1;
return;
}
if (v<=mid){
c[t].rson=c[_t].rson;
modify(l,mid,c[t].lson=++num,v,c[_t].lson);
}else{
c[t].lson=c[_t].lson;
modify(mid+1,r,c[t].rson=++num,v,c[_t].rson);
}
c[t].x=c[c[t].lson].x+c[c[t].rson].x;
c[t].l=c[c[t].rson].l+c[c[t].lson].l+c[c[t].rson].x*(mid-l+1);
c[t].r=c[c[t].lson].r+c[c[t].rson].r+c[c[t].lson].x*(r-mid);
}
ll query(ll l,ll r,ll t,ll v,ll _t){
ll mid=(l+r)/2;
if (r<=v) return c[t].r-c[_t].r+(c[t].x-c[_t].x)*(v-r);
if (l>=v) return c[t].l-c[_t].l+(c[t].x-c[_t].x)*(l-v);
return query(l,mid,c[t].lson,v,c[_t].lson)+query(mid+1,r,c[t].rson,v,c[_t].rson);
}
ll getmid(ll l,ll r,ll t,ll _t,ll ls,ll rs){
ll mid=(l+r)/2,L=c[c[t].lson].x-c[c[_t].lson].x+ls,R=c[c[t].rson].x-c[c[_t].rson].x+rs;
if (l==r) return l;
if (L<R) return getmid(mid+1,r,c[t].rson,c[_t].rson,L,rs);
else if (L>R) return getmid(l,mid,c[t].lson,c[_t].lson,ls,R);
else return mid;
}
ll mincost(ll l,ll r){return query(1,2e9+1,rt[r],getmid(1,2e9+1,rt[r],rt[l],0,0),rt[l]);}
void dfs(ll j,ll l,ll r,ll L,ll R){
ll mid=(l+r)/2,tmd=0;
if (l>r) return;
fo(k,L,min(mid-1,R)){
if (f(k,j-1)<lim){
ll tmp=f(k,j-1)+mincost(k,mid);
if (tmp<f(mid,j)){
f(mid,j)=tmp;
tmd=k;
}
if (n==mid) ans=min(f(mid,j),ans);
}
}
dfs(j,l,mid-1,L,tmd);
dfs(j,mid+1,r,tmd,R);
}
int main(){
freopen(fin,"r",stdin);
freopen(fout,"w",stdout);
scanf("%lld%lld",&n,&m);
fo(i,1,n){
scanf("%lld%lld",&a[i].x,&a[i].y);
a[i].x+=1e9+1;
a[i].y+=1e9+1;
}
sort(a+1,a+n+1,cmp);
memset(f,127,sizeof(f));
lim=f[0];
ans=f[0];
f(0,0)=0;
rt[0]=0;
fo(i,1,n){
modify(1,2e9+1,rt[i]=++num,a[i].x,rt[i-1]);
modify(1,2e9+1,rt[i],a[i].y,rt[i]);
}
fo(j,1,m)
dfs(j,1,n,0,n);
printf("%lld",ans);
return 0;
}