题解:首先将块排个序,然后去掉被其它某块包含的块,然后斜率优化dp
dp方程:f[i]=f[j]+a[i]*b[j+1];
具体什么x啊y啊什么的在代码注释里面。
……。。。。纠结死了。开始各种WA,现在才发现:
inline long long xmul(Point i,Point j,Point k){(i.y-j.y)*(j.x-k.x)-(j.y-k.y)*(i.x-j.x);}
上面的代码竟然能通过编译……,无力吐槽。以后一定要用终端+Wall命令编译文件了。
warning一日不死,代码一日不跑!!!!
……调了好久好久好久啊。。。。。。。心痛啊。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 50500
#define inf 0x3f3f3f3f
/*
f[j]=-a[i]*b[j+1]+f[i]
y=f[j]
x=b[j+1]
k=-a[i] 保证a不降,即k不升
b=f[i]
维护上凸包
*/
using namespace std;
struct Point
{
long long x,y;
int id;
Point(long long _x,long long _y,int _id):x(_x),y(_y),id(_id){}
Point(){}
}now,que[N];
inline long long xmul(Point i,Point j,Point k){return(i.y-j.y)*(j.x-k.x)-(j.y-k.y)*(i.x-j.x);}
int n,l,r;
long long f[N];
struct Mrx
{
long long a,b;
bool operator < (const Mrx &c)const
{if(a==c.a)return b<c.b;return a<c.a;}
}mrx[N];
int main()
{
// freopen("test.in","r",stdin);
// freopen("my.out","w",stdout);
int i,j,k;
scanf("%d",&n);
for(i=1;i<=n;i++)scanf("%d%d",&mrx[i].a,&mrx[i].b);
sort(mrx+1,mrx+n+1);
int edl=0;
long long maxx=0;
for(i=n;i;i--)
{
if(mrx[i].b<=maxx)edl++,mrx[i].a=mrx[i].b=inf;
else maxx=mrx[i].b;
}
sort(mrx+1,mrx+n+1);
n-=edl;
memset(f,0x3f,sizeof(f));
f[0]=0;
que[0].x=mrx[1].b;
for(i=1;i<=n;i++)
{
int K=-mrx[i].a;
// while(l<r&&que[l].y-que[l+1].y>=(que[l].x-que[l+1].x)*K)l++; //斜率版
while(l<r&&f[que[l].id]+mrx[i].a*mrx[que[l].id+1].b>=f[que[l+1].id]+mrx[i].a*mrx[que[l+1].id+1].b)l++; //函数值版
now=Point(mrx[i+1].b,f[i]=f[que[l].id]+mrx[i].a*mrx[que[l].id+1].b,i);
while(l<r&&xmul(now,que[r],que[r-1])>=0)r--;
// while(l<r&&(now.y-que[r].y)*(que[r].x-que[r-1].x)>=(que[r].y-que[r-1].y)*(now.x-que[r].x))--r;
que[++r]=now;
}
cout<<f[n]<<endl;
return 0;
}
。。。。。