zoukankan      html  css  js  c++  java
  • 斜率优化(CDQ分治,Splay平衡树):BZOJ 1492: [NOI2007]货币兑换Cash

    Description

    Input

    第一行两个正整数N、S,分别表示小Y 能预知的天数以及初始时拥有的钱数。 接下来N 行,第K 行三个实数AK、BK、RateK,意义如题目中所述

    Output

    只有一个实数MaxProfit,表示第N 天的操作结束时能够获得的最大的金钱 数目。答案保留3 位小数。

    Sample Input

    3 100
    1 1 1
    1 2 2
    2 2 3

    Sample Output

    225.000

    HINT



    测试数据设计使得精度误差不会超过10-7。
    对于40%的测试数据,满足N ≤ 10;
    对于60%的测试数据,满足N ≤ 1 000;
    对于100%的测试数据,满足N ≤ 100 000;

     
     1 #include <iostream>
     2 #include <cstring>
     3 #include <cstdio>
     4 #include <algorithm>
     5 using namespace std;
     6 const double eps=1e-8;
     7 const int maxn=100010;
     8 struct Node{
     9     double a,b,r,x,y,k;
    10     int id;
    11 }d[maxn],t[maxn];
    12 double f[maxn];
    13 int st[maxn],cnt,n;
    14 double Abs(double a){return a>0?a:-a;}
    15 double K(int a,int b){
    16     if(Abs(d[a].x-d[b].x)<eps)return 1e20;
    17     return (d[a].y-d[b].y)/(d[a].x-d[b].x);
    18 }
    19 void Solve(int l,int r){
    20     if(l==r){
    21         f[l]=max(f[l],f[l-1]);
    22         d[l].y=f[l]/(d[l].r*d[l].a+d[l].b);
    23         d[l].x=d[l].y*d[l].r;
    24         return;
    25     }
    26     int mid=(l+r)>>1,t1=l,t2=mid+1;
    27     for(int i=l;i<=r;i++){
    28         if(d[i].id<=mid)
    29             t[t1++]=d[i];
    30         else 
    31             t[t2++]=d[i];
    32     }
    33     for(int i=l;i<=r;i++)d[i]=t[i];
    34     Solve(l,mid);
    35     cnt=0;
    36     for(int i=l;i<=mid;i++){
    37         while(cnt>1&&K(i,st[cnt])-K(st[cnt],st[cnt-1])>=eps)cnt--;
    38         st[++cnt]=i;
    39     }
    40     int fir=1;
    41     for(int i=mid+1;i<=r;i++){
    42         while(fir<cnt&&K(st[fir+1],st[fir])-d[i].k>=eps)fir++;
    43         f[d[i].id]=max(f[d[i].id],d[st[fir]].x*d[i].a+d[st[fir]].y*d[i].b);
    44     }
    45     Solve(mid+1,r);
    46     t1=l;t2=mid+1;
    47     for(int i=l;i<=r;i++){
    48         if(t2==r+1||(d[t2].x-d[t1].x>=eps||Abs(d[t2].x-d[t1].x)<eps&&d[t2].y-d[t1].y>=eps)&&t1<=mid)
    49             t[i]=d[t1++];
    50         else    
    51             t[i]=d[t2++];
    52     }    
    53     for(int i=l;i<=r;i++)
    54         d[i]=t[i];
    55 }
    56 
    57 
    58 bool cmp(Node a,Node b){
    59     return a.k>b.k;
    60 }
    61 int main(){
    62     scanf("%d%lf",&n,&f[1]);
    63     for(int i=1;i<=n;i++){
    64         scanf("%lf%lf%lf",&d[i].a,&d[i].b,&d[i].r);
    65         d[i].k=-d[i].a/d[i].b;
    66         d[i].id=i;
    67     }
    68     sort(d+1,d+n+1,cmp);
    69     Solve(1,n);
    70     printf("%.3lf
    ",f[n]);
    71     return 0;
    72 }

      这里还有Splay。

      1 #include <iostream>
      2 #include <cstring>
      3 #include <cstdio>
      4 using namespace std;
      5 const double eps=1e-8;
      6 const double INF=1e20;
      7 const int maxn=100010;
      8 int ch[maxn][2],fa[maxn],rt,tot,n;
      9 double X[maxn],Y[maxn],lk[maxn],rk[maxn],ans;
     10 double fabs(double x){return (x>0)?x:-x;}
     11 void Rotate(int x){
     12     int y=fa[x],g=fa[y],c=ch[y][1]==x;
     13     ch[y][c]=ch[x][c^1];fa[ch[y][c]]=y;
     14     ch[x][c^1]=y;fa[y]=x;fa[x]=g;
     15     if(g)ch[g][ch[g][1]==y]=x;
     16 }
     17 
     18 void Splay(int x,int g=0){
     19     for(int y;(y=fa[x])!=g;Rotate(x))
     20         if(fa[y]!=g)Rotate((ch[fa[y]][1]==y)==(ch[y][1]==x)?y:x);
     21     if(!g)rt=x;    
     22 }
     23 
     24 double Get_K(int j,int k){
     25     if(fabs(X[j]-X[k])<=eps)return INF;
     26     else return (Y[j]-Y[k])/(X[j]-X[k]);
     27 }
     28 
     29 int Get_Prev(){
     30     int p=ch[rt][0],ret=p;
     31     while(p){
     32         if(Get_K(rt,p)+eps>=lk[p])p=ch[p][0];
     33         else ret=p,p=ch[p][1];
     34     }
     35     return ret;
     36 }
     37 
     38 int Get_Succ(){
     39     int p=ch[rt][1],ret=p;
     40     while(p){
     41         if(Get_K(p,rt)<=rk[p]+eps)p=ch[p][1];
     42         else ret=p,p=ch[p][0];
     43     }
     44     return ret;
     45 }
     46 
     47 void Insert(int &r,int pre,int p){
     48     if(r==0){r=p;fa[p]=pre;return;}
     49     if(X[p]<=X[r]+eps)Insert(ch[r][0],r,p);
     50     else Insert(ch[r][1],r,p);
     51 }
     52 
     53 void Update(int p){
     54     Splay(p);
     55     if (ch[p][0]){
     56         int l=Get_Prev();
     57         Splay(l,p);ch[l][1]=0;
     58         lk[p]=rk[l]=Get_K(p,l);
     59     }
     60     else lk[p]=INF;
     61     if (ch[p][1]){
     62         int r=Get_Succ();
     63         Splay(r,p); ch[r][0]=0;
     64         rk[p]=lk[r]=Get_K(r,p);
     65     }
     66     else rk[p]=-INF;
     67     if (lk[p]<=rk[p]+eps){
     68         rt=ch[p][0]; ch[rt][1]=ch[p][1]; fa[ch[p][1]]=rt; fa[rt]=0;
     69         rk[rt]=lk[ch[p][1]]=Get_K(ch[rt][1],rt);
     70     }
     71 } 
     72 
     73 int Get_Pos(double k){
     74     int p=rt;
     75     while(p){
     76         if(lk[p]+eps>=k&&k+eps>=rk[p])break;
     77         if(lk[p]<k+eps)p=ch[p][0];
     78         else p=ch[p][1];
     79     }
     80     return p;
     81 }
     82 
     83 double Get_Ans(double a,double b){
     84     int p=Get_Pos(-b/a);
     85     return a*Y[p]+b*X[p];
     86 }
     87 
     88 int main(){
     89 #ifndef ONLINE_JUDGE
     90     freopen("cash.in","r",stdin);
     91     freopen("cash.out","w",stdout);
     92 #endif
     93     double a,b,rate;
     94     scanf("%d%lf",&n,&ans);
     95     for(int i=1;i<=n;i++){
     96         scanf("%lf%lf%lf",&a,&b,&rate);
     97         if(i!=1)ans=max(ans,Get_Ans(a,b));
     98         X[i]=ans/(rate*a+b);
     99         Y[i]=X[i]*rate;
    100         Insert(rt,0,i);
    101         Update(i);    
    102     }
    103     printf("%.3f
    ",ans);
    104     return 0;
    105 }
    尽最大的努力,做最好的自己!
  • 相关阅读:
    HDU 3681 Prison Break 越狱(状压DP,变形)
    POJ 2411 Mondriaan's Dream (状压DP,骨牌覆盖,经典)
    ZOJ 3471 Most Powerful (状压DP,经典)
    POJ 2288 Islands and Bridges (状压DP,变形)
    HDU 3001 Travelling (状压DP,3进制)
    POJ 3311 Hie with the Pie (状压DP)
    POJ 1185 炮兵阵地 (状压DP,轮廓线DP)
    FZU 2204 7
    POJ 3254 Corn Fields (状压DP,轮廓线DP)
    ZOJ 3494 BCD Code (数位DP,AC自动机)
  • 原文地址:https://www.cnblogs.com/TenderRun/p/5307998.html
Copyright © 2011-2022 走看看