BZOJ1492: [NOI2007]货币兑换Cash

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1492

CDQ分治论文上的题《从《Cash》谈一类分治算法的应用cdq》。膜hzw学长的博客膜了好久。

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6 #define inf 1<<30
 7 #define maxn 100005
 8 #define eps 1e-9
 9 using namespace std;
10 int n,top,stack[maxn];
11 double f[maxn];
12 struct fuck{double x,y,a,b,rate,k; int id;}p[maxn],t[maxn];
13 bool cmp(fuck x,fuck y){return x.k>y.k;}
14 double getk(int a,int b){
15     if(!b) return -1e20;
16     if(fabs(p[a].x-p[b].x)<eps) return 1e20;
17     return (p[b].y-p[a].y)/(p[b].x-p[a].x);
18 }
19 void solve(int l,int r){
20     if(l==r){
21         f[l]=max(f[l],f[l-1]);
22         p[l].y=f[l]/(p[l].a*p[l].rate+p[l].b);
23         p[l].x=p[l].rate*p[l].y;
24         return;
25     }
26     int mid=(l+r)>>1,l1=l,l2=mid+1;
27     for(int i=l;i<=r;i++)
28     if(p[i].id<=mid) t[l1++]=p[i];
29     else t[l2++]=p[i];
30     for(int i=l;i<=r;i++) p[i]=t[i];
31     solve(l,mid);
32     top=0;
33     for(int i=l;i<=mid;i++){
34         while(top&&getk(stack[top-1],stack[top])<getk(stack[top],i)+eps) top--;
35         stack[++top]=i;
36     }
37     stack[++top]=0;
38     for(int i=mid+1,j=1;i<=r;i++){
39         while(j<top&&getk(stack[j],stack[j+1])+eps>p[i].k) j++;
40         f[p[i].id]=max(f[p[i].id],p[stack[j]].x*p[i].a+p[stack[j]].y*p[i].b);
41     }
42     solve(mid+1,r);
43     l1=l;l2=mid+1;
44     for(int i=l;i<=r;i++)
45     if(((p[l1].x<p[l2].x||(fabs(p[l1].x-p[l2].x)<eps&&p[l1].y<p[l2].y))||l2>r)&&l1<=mid) t[i]=p[l1++];
46     else t[i]=p[l2++];
47     for(int i=l;i<=r;i++)p[i]=t[i];
48 }
49 int main(){
50     scanf("%d%lf",&n,&f[0]);
51     for(int i=1;i<=n;i++){
52         scanf("%lf%lf%lf",&p[i].a,&p[i].b,&p[i].rate);
53         p[i].k=-p[i].a/p[i].b; p[i].id=i;
54     }
55     sort(p+1,p+n+1,cmp);
56     solve(1,n);
57     printf("%0.3lf",f[n]);
58     return 0;
59 }
View Code

 

posted @ 2016-05-24 15:58  I'mLS  阅读(163)  评论(2编辑  收藏  举报