bzoj1492货币兑换Cash

题意:有A,B两种纪念券,最初由S元,有n天,每天有A,B的价值并可以以任意比例购买或卖出A,B两券,求最后能剩多少钱。

有一个点很明显,对于每一天,要么全买,要么全卖。

记f(i)为第i天最多能有多少钱,X[i]表示第i天最多能有多少A券,Y[i]为B券

则Y[j]=f[j]/(b[j]+a[j]*rate[j])

   X[j]=Y[j]*rate[j]

 f[i]=max(f[i-1],a[i]*X[j]+b[i]*Y[j])

 Y[j]=-a[i]/b[i]*X[j]+f[i]/b[i]

然后斜率优化搞一搞,发现斜率不单调,可以用splay维护一下。

当然,还是CDQ大发好。

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

 

posted @ 2016-12-12 11:53  yanglang  阅读(130)  评论(0编辑  收藏  举报