CDQ分治模板
#include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #define eps 1e-9 using namespace std; const int M=200010; int n,i,top,stack[M]; double f[M]; struct shit{double x,y,k,a,b,rate;int id;}p[M],q[M]; bool cmp(shit x,shit y){return x.k>y.k;} double K(int x,int y){ if (!y)return -1e20; if (fabs(q[x].x-q[y].x)<eps)return 1e20; return (q[y].y-q[x].y)/(q[y].x-q[x].x); } void cdq(int l,int r){ int mid=l+r>>1,L=l,R=mid+1,j=1; if (l==r){ f[l]=max(f[l],f[l-1]); q[l].y=f[l]/(q[l].rate*q[l].a+q[l].b); q[l].x=q[l].y*q[l].rate; return; 更新ans,利用已经计算好的l的最优决策k,计算f [l]值,Exit } for (int i=l;i<=r;i++) if (q[i].id<=mid)p[L++]=q[i]; else p[R++]=q[i]; for (int i=l;i<=r;i++)q[i]=p[i]; cdq(l,mid); top=0; for (int i=l;i<=mid;i++){ while (top>1&&K(stack[top-1],stack[top])<K(stack[top-1],i)+eps)top--; stack[++top]=i; 对[l, mid-1]这一段扫描一遍计算出决策的凸线, } stack[++top]=0; for (int i=mid+1;i<=r;i++){ while (j<top&&K(stack[j],stack[j+1])+eps>q[i].k)j++; f[q[i].id]=max(f[q[i].id],q[stack[j]].x*q[i].a+q[stack[j]].y*q[i].b); 由于[mid+1 .. r]这一段以 -a[i] / b[i]的排序在预处理已经完成, 因此只需要扫描一遍更新[mid + 1 .. r] 的最优决策. } cdq(mid+1,r); L=l,R=mid+1; for (int i=l;i<=r;i++) if (((q[L].x<q[R].x||(fabs(q[L].x-q[R].x)<eps&&q[L].y<q[R].y))||R>r)&&L<=mid)p[i]=q[L++]; else p[i]=q[ ++]; for (int i=l;i<=r;i++)q[i]=p[i]; 利用[l, mid-1]已排好序的f []值和[mid+1, r]已排好序的f []值归并排序将 [l, r]这一段按f[]值排序. } int main(){ scanf("%d%lf",&n,&f[0]); for (i=1;i<=n;i++){ scanf("%lf%lf%lf",&q[i].a,&q[i].b,&q[i].rate); q[i].k=-q[i].a/q[i].b; q[i].id=i; } sort(q+1,q+n+1,cmp); cdq(1,n); printf("%.3lf\n",f[n]); }
null