BZOJ 1492 [NOI2007]货币兑换Cash

题解:

题意不能说明白了?????

比例到底是数量还是价值??????

平衡树维护凸包

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
const int maxn=200009;
const int oo=1000000000;
const double eps=1e-9;

int dcmp(double x){
    if(fabs(x)<eps)return 0;
    if(x>0)return 1;
    else return -1;
}

int n;
double A[maxn],B[maxn],R[maxn],f[maxn];
double Getx(int i){
    return f[i]*R[i]/(R[i]*A[i]+B[i]);
}
double Gety(int i){
    return f[i]/(R[i]*A[i]+B[i]);
}
double GetK(int i,int j){
    double xi=Getx(i),yi=Gety(i);
    double xj=Getx(j),yj=Gety(j);
    return (yi-yj)/(xi-xj);
}

int nn=0,root=0;
int fa[maxn]={0},ch[maxn][2]={0};
double lk[maxn],rk[maxn];

int son(int x){
    if(ch[fa[x]][0]==x)return 0;
    else return 1;
}

void Rotate(int x){
    int y=fa[x];
    int z=fa[y];
    int b=son(x),c=son(y);
    int a=ch[x][b^1];
    if(z)ch[z][c]=x;
    else root=x;
    fa[x]=z;
    if(a)fa[a]=y;
    ch[y][b]=a;
    fa[y]=x;ch[x][b^1]=y;
}

void Splay(int x,int i){
    while(fa[x]!=i){
        int y=fa[x];
        int z=fa[y];
        if(z==i){
            Rotate(x);
        }else{
            if(son(x)==son(y)){
                Rotate(y);Rotate(x);
            }else{
                Rotate(x);Rotate(x);
            }
        }
    }
}

void Del(){
    int x=root;
    if((!ch[x][0])&&(!ch[x][1])){
        root=0;
    }else if(!ch[x][0]){
        root=ch[x][1];
        fa[ch[x][1]]=0;
        lk[ch[x][1]]=oo;
    }else if(!ch[x][1]){
        root=ch[x][0];
        fa[ch[x][0]]=0;
        rk[ch[x][0]]=-oo;
    }else{
        int pre=ch[x][0];
        int suc=ch[x][1];
        while(ch[pre][1])pre=ch[pre][1];
        while(ch[suc][0])suc=ch[suc][0];
        Splay(pre,x);Splay(suc,x);
        ch[pre][1]=suc;fa[suc]=pre;
        root=pre;fa[pre]=0;
        rk[pre]=lk[suc]=GetK(pre,suc);
    }
}

void Ins(int p){
    double xp=Getx(p);
    int x=root,y=0;
//    cout<<"inseting"<<endl;
    while(x){
        y=x;
        double xi=Getx(x);
        if(dcmp(xi-xp)==0){
            if(dcmp(Gety(x)-Gety(p))>=0){
                return;
            }else{
                Splay(x,0);Del();Ins(p);return;
            }
        }
        if(xp>xi)x=ch[x][1];
        else x=ch[x][0];
    }
//    cout<<"endinseting"<<endl;
    fa[x=p]=y;
    if(!y){
        root=x;
    }else{
        if(Getx(x)>Getx(y))ch[y][1]=x;
        else ch[y][0]=x;
    }
    Splay(x,0);
    int pre=ch[x][0];
    while(ch[pre][1])pre=ch[pre][1];
    int suc=ch[x][1];
    while(ch[suc][0])suc=ch[suc][0];
    if(!pre)lk[x]=oo;
    else lk[x]=rk[pre]=GetK(x,pre);
    if(!suc)rk[x]=-oo;
    else rk[x]=lk[suc]=GetK(x,suc);
}

void QueryK(double k){
    int x=root;
    while(x){
        if(lk[x]>=k&&rk[x]<=k){
            Splay(x,0);return;
        }else if(rk[x]>=k){
            if(ch[x][1]){
                x=ch[x][1];
            }else{
                Splay(x,0);return;
            }
        }else{
            if(ch[x][0]){
                x=ch[x][0];
            }else{
                Splay(x,0);return;
            }
        }
    }
}

void Getrk(int x,int p){
    int y=0;
    while(x){
        if(dcmp(lk[x]-GetK(x,p)>=0)){
            y=x;x=ch[x][1];
        }else{
            x=ch[x][0];
        }
    }
    if(y==0)return;
    Splay(y,p);
    ch[y][1]=0;
    rk[y]=lk[p]=GetK(y,p);
}
void Getlk(int x,int p){
    int y=0;
    while(x){
        if(dcmp(rk[x]-GetK(x,p))<=0){
            y=x;x=ch[x][0];
        }else{
            x=ch[x][1];
        }
    }
    if(y==0)return;
    Splay(y,p);
    ch[y][0]=0;
    rk[p]=lk[y]=GetK(y,p);
}

int main(){
    scanf("%d%lf",&n,&f[0]);
    for(int i=1;i<=n;++i)scanf("%lf%lf%lf",&A[i],&B[i],&R[i]);
    
    for(int i=1;i<=n;++i){
        double k;
        if(dcmp(B[i])==0)k=-oo;
        else k=-A[i]/B[i];
        
        f[i]=f[i-1];
        QueryK(k);
        if(root)f[i]=max(f[i],(A[i]*Getx(root)+B[i]*Gety(root)));
        
        Ins(i);
        if(root!=i)continue;
        if(lk[i]<rk[i]){
            Del();
        }else{
            if(ch[i][0]){
                Getrk(ch[i][0],i);
            }
            if(ch[i][1]){
                Getlk(ch[i][1],i);
            }
        }
    }
    
    printf("%.3f\n",f[n]);
    return 0;
}

 

posted @ 2018-03-20 16:35  ws_zzy  阅读(205)  评论(0编辑  收藏  举报