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 }