解题思路:
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
struct node
{
ll w,h;
}s1[50009],s[50009];
ll dp[50009][105];
int stk[50009];
const int inf=0x3f3f3f3f;
bool cmp(node a,node b)
{
if(a.w==b.w)
return a.h>b.h;
return a.w>b.w;
}
ll getdp(int j,int i,int m)
{
return dp[j][m]+s[j+1].w*s[i].h;
}
ll getup(int j1,int j2,int m)
{
return dp[j1][m]-dp[j2][m];
}
ll getdown(int j1,int j2)
{
return s[j2+1].w-s[j1+1].w;
}
int main()
{
int n,k;
//freopen("t.txt","r",stdin);
while(scanf("%d%d",&n,&k)!=EOF)
{
for(int i=1;i<=n;i++)
{
scanf("%lld%lld",&s1[i].w,&s1[i].h);
}
sort(s1+1,s1+n+1,cmp);
int ct=0;
s[++ct]=s1[1];
for(int i=2;i<=n;i++)
{
if(s1[i].h>s[ct].h)
s[++ct]=s1[i];
}
for(int i=1;i<=ct;i++)
{
dp[i][1]=s[1].w*s[i].h;
}
ll ans=dp[ct][1];
for(int m=2;m<=k;m++)
{
int head=0,tail=0;
stk[tail++]=m-1;
dp[ct][m]=inf;
for(int i=m;i<=ct;i++)
{
while(head+1<tail&&getup(stk[head+1],stk[head],m-1)<s[i].h*getdown(stk[head+1],stk[head]))
head++;
dp[i][m]=getdp(stk[head],i,m-1);
while(head+1<tail&&getup(stk[tail-1],stk[tail-2],m-1)*getdown(i,stk[tail-1])>getup(i,stk[tail-1],m-1)*getdown(stk[tail-1],stk[tail-2]))
tail--;
stk[tail++] =i;
}
if(ans<=dp[ct][m])
break;
else
ans=dp[ct][m];
}
printf("%lld\n",ans);
}
return 0;
}