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
",f[n]);
}
原文地址:https://www.cnblogs.com/myx12345/p/6439894.html