bzoj1492(cdq分治+凸包+优化dp)

来源:互联网 发布:百慕达网络超市 编辑:程序博客网 时间:2024/06/05 00:11

我们会发现dp不满足单调性,但是可以构建凸包,其中点的表示方法很巧妙

 

要对一些问题转化成凸包敏感一点,尝试找出表示凸包的点,看看是否可以用斜率来表示答案。

 

一定要写eps,wa到死。。。

 

在cdp分治如果预先,处理了某一维信息相对的顺序,那么在分治中千万不能打破这个顺序!!!!

 

#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#include<cstdlib>#include<queue>using namespace std;const int N=120005;int n,st[N];double f[N],a[N],b[N],rate[N];const double eps=1e-9;struct vec{double x,y;};typedef vec point;point p[N],pp[N];struct aa{    double k;    int id;}t[N],t1[N];bool cmp(aa a,aa b) {return a.k<b.k;}bool operator <(point a,point b) {return a.x<b.x||(fabs(a.x-b.x)<eps&&a.y<b.y);}double get(int a,int b){if (fabs(p[a].x-p[b].x)<eps) return -1e9;return (p[a].y-p[b].y)/(p[a].x-p[b].x);}void work(int l,int r) {    if (l==r)     {        f[l]=max(f[l],f[l-1]);        p[l].y=f[l]/(rate[l]*a[l]+b[l]);        p[l].x=p[l].y*rate[l];        return ;    }    int mid=(l+r)>>1,ll=l,rr=mid+1;         for (int i=l;i<=r;i++) if (t[i].id<=mid) t1[ll++]=t[i];else t1[rr++]=t[i];//已经排好序了,绝对不能改变相对顺序!!!    for (int i=l;i<=r;i++) t[i]=t1[i];    work(l,mid);        int sz=0;    for (int i=l;i<=mid;i++)     {        while (sz>1&&get(i,st[sz])+eps>get(st[sz],st[sz-1])) sz--;        st[++sz]=i;    }    int now=1;    for (int i=r;i>mid;i--)     {        while (now<sz&&get(st[now+1],st[now])>t[i].k) now++;        int pos=t[i].id;        f[pos]=max(f[pos],p[st[now]].y*b[pos]+p[st[now]].x*a[pos]);    }         work(mid+1,r);    int h = l, t = mid + 1;    for(int i = l; i <= r; ++i)        if ((p[h] < p[t] || t > r) && h <= mid) pp[i] = p[h++];        else pp[i] = p[t++];    for(int i = l; i <= r; ++i) p[i] = pp[i];} int main(){    scanf("%d%lf",&n,&f[0]);     for (int i=1;i<=n;i++) scanf("%lf%lf%lf",&a[i],&b[i],&rate[i]),t[i].k=-a[i]/b[i],t[i].id=i;    sort(t+1,t+n+1,cmp);    work(1,n);    printf("%.3lf",f[n]);    return 0;}


 

0 0
原创粉丝点击