在st讲课时,学习了以前GG很久的cdq,写了一些例题,算是入门了?
cdq优化dp(凸包上三分)
dp[i]=max(dp[j],a[j]*va[i]+b[j] *vb[i]);
//QWsin
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=200000+10;
const double eps=1e-11;
inline int dcmp(double x){if(fabs(x)<eps) return 0;return x<0?-1:1;}
int n;
double dp[maxn],a[maxn],b[maxn];
double va[maxn],vb[maxn],rate[maxn];
struct point{
double x,y;
point (double x=0,double y=0):x(x),y(y){}
inline bool operator < (const point &rhs)const{
return x<rhs.x||(dcmp(x-rhs.x)==0&&y<rhs.y);
}
}p[maxn];
typedef point vc;
vc operator - (const point &a,const point &b){return vc(a.x-b.x,a.y-b.y);}
inline double cross(const vc &a,const vc &b){return a.x*b.y-a.y*b.x;}
inline double dot(const vc &a,const vc &b){return a.x*b.x+a.y*b.y;}
inline double check(int l,int r,vc V)
{
while(r-l+1 > 3)
{
int mid1=(l+l+r)/3;
int mid2=(l+r+r)/3;
double v1=dot(p[mid1],V);
double v2=dot(p[mid2],V);
if(dcmp(v1-v2)>=0) r=mid2;//****三分注意上凸下凸
else l=mid1;
}
double ans=0;
for(int i=l;i<=r;++i) ans=max(ans,dot(p[i],V));
return ans;
}
void solve(int l,int r)
{
if(l==r){
dp[l]=max(dp[l-1],dp[l]);
b[l]=dp[l]/(rate[l]*va[l]+vb[l]);
a[l]=b[l]*rate[l];
return ;
}
int mid=(l+r)>>1;
solve(l,mid);
int top=0;
for(int i=l;i<=mid;++i)
{
point t(a[i],b[i]);
while(top>1&&cross(p[top]-p[top-1],t-p[top]) > -eps) --top;
p[++top]=t;
}
for(int i=mid+1;i<=r;++i)
{
double tmp=check(1,top,point(va[i],vb[i]));
dp[i]=max(dp[i],tmp);
}
solve(mid+1,r);
sort(p+l,p+r+1);
}
int main()
{
cin>>n;scanf("%lf",dp+0);
for(int i=1;i<=n;++i) {
scanf("%lf%lf%lf",va+i,vb+i,rate+i);
}
solve(1,n);
printf("%.3f\n",dp[n]);
return 0;
}