正题
题目直接戳这里
首先,要贪心一点,我们肯定会选在j天买入i天卖出收益最大的时候整体买入和整体卖出。
所以很明显就有一个Dp方程。
其中ai指的是在这时候a卷的价值,bi同理。
xj表示在j的时候买的最多的xj的卷数。
yj同理
然后遇到这种东西不知道怎么办就只能暴力找。
n的平方。
想着怎么优化。
化简一下。
诶.y=kx+b耶。想使得f(i)最大,那么必须使得b(截距)最大。那么很明显,用前i-1个点在笛卡尔坐标系上描点,用斜率为的直线从上往下扫,碰到的第一个点就是能使i获得最大价值的j。明显是个上凸包。但是题目没有保证有序,所以不能用单调队列来维护。想想,是不是还有CDQ分治啊。
所以我们把每一个i按照对应的斜率进行排序。
每次分的时候,我们把i分成左右两堆,一堆的初始序是小于等于mid,一堆的初始序是大于mid的,那么现在可以保证,左右两堆虽然不是按顺序的,但是去到了自己要去的地方,而且是按斜率排序的。
每次处理完左边,就要计算一下左边对右边产生的影响。
用左边构造一个上凸包,又因为右边的斜率是有序的,所以我们可以花(r-l+1)/2的时间扫完整个凸包,并且获得右边一些点的答案(因为有些点的答案不存在于这些点内)。
处理完左右两边,我们按照x排序,返回,这样又可以使得上一层可以O(n)构造凸包。
另外和是可以通过解一个一元二次方程得到的(当然要知道f(i)才能求)。
另外,做这种毒瘤题一定要注意精度
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<vector>
using namespace std;
int n;
double eps=1e-8;
double INF=1e20;
struct node{
double a,b,r,k,x,y;
int id;
bool operator<(const node p)const{
return k>p.k;
}
}q[100010],t[100010];
double f[100010];
int op[100010];
double get_k(int a,int b){
if(b==0) return -INF;
if(fabs(q[a].x-q[b].x)<eps) return INF;
return (q[b].y-q[a].y)/(q[b].x-q[a].x);
}
void solve(int l,int r){
if(l==r){
f[l]=max(f[l-1],f[l]);
q[l].y=f[l]/(q[l].a*q[l].r+q[l].b);
q[l].x=q[l].y*q[l].r;
return ;
}
int mid=(l+r)/2;
int left=l,right=mid+1;
for(int i=l;i<=r;i++)
if(q[i].id<=mid) t[left++]=q[i];
else t[right++]=q[i];
for(int i=l;i<=r;i++) q[i]=t[i];
solve(l,mid);
int tt=0;
for(int i=l;i<=mid;i++){
while(tt>1 && get_k(op[tt-1],op[tt])<get_k(op[tt-1],i)+eps) tt--;
op[++tt]=i;
}
op[++tt]=0;
int now=1;
for(int i=mid+1;i<=r;i++){
while(now<tt && get_k(op[now],op[now+1])+eps>q[i].k) now++;
f[q[i].id]=max(f[q[i].id],q[op[now]].x*q[i].a+q[op[now]].y*q[i].b);
}
solve(mid+1,r);
left=l,right=mid+1;
for(int i=l;i<=r;i++)
if(((q[left].x<q[right].x||(fabs(q[left].x-q[right].x)<eps && q[left].y<q[right].y))||right>r)&&left<=mid)
t[i]=q[left++];
else t[i]=q[right++];
for(int i=l;i<=r;i++) q[i]=t[i];
return ;
}
int main(){
scanf("%d %lf",&n,&f[0]);
for(int i=1;i<=n;i++){
scanf("%lf %lf %lf",&q[i].a,&q[i].b,&q[i].r);
q[i].k=-q[i].a/q[i].b;
q[i].id=i;
}
sort(q+1,q+1+n);
solve(1,n);
printf("%.3lf",f[n]);
}