• BZOJ 1492 货币兑换Cash


    http://www.lydsy.com/JudgeOnline/problem.php?id=1492

    思路:

    问题转变为维护一个凸包,每次转移都找凸包上的点,并更新凸壳

    可以用splay维护,或者说,可以用cdq分治去维护,左半边构成的凸壳对右半边答案的影响~

    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    #include<iostream>
    const double eps=1e-9;
    double f[500005];
    struct node{
        double a,b,rate,x,y,k;
        int id;
    }p[500005],tmp[500005];
    int n,stack[500005];
    int read(){
        int t=0,f=1;char ch=getchar();
        while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
        while ('0'<=ch&&ch<='9'){t=t*10+ch-'0';ch=getchar();}
        return t*f;
    }
    bool cmp(node a,node b){
        return a.k>b.k;
    }
    double getk(int a,int b){
        if (!b) return -1e20;
        if (fabs(p[a].x-p[b].x)<eps) return 1e20;
        return (p[b].y-p[a].y)/(p[b].x-p[a].x);
    }
    void cdq(int l,int r){
        if (l==r){
            f[l]=std::max(f[l],f[l-1]);
            p[l].y=f[l]/(p[l].a*p[l].rate+p[l].b);
            p[l].x=p[l].rate*p[l].y;
            return;
        }
        int mid=(l+r)>>1;
        int l1=l-1,l2=mid;
        for (int i=l;i<=r;i++)
            if (p[i].id<=mid)
                tmp[++l1]=p[i];
            else
                tmp[++l2]=p[i];
        for (int i=l;i<=r;i++)
            p[i]=tmp[i];
        cdq(l,mid);
        int top=0;
        for (int i=l;i<=mid;i++){
             while (top>1&&getk(stack[top-1],stack[top])<getk(stack[top-1],i)+eps) top--;
                 stack[++top]=i;
        }
        stack[++top]=0;int j=1;
        for (int i=mid+1;i<=r;i++){
             while (j<top&&getk(stack[j],stack[j+1])+eps>p[i].k) j++;
             f[p[i].id]=std::max(f[p[i].id],p[stack[j]].x*p[i].a+p[stack[j]].y*p[i].b);
        }
        cdq(mid+1,r);
        l1=l,l2=mid+1;
        for (int i=l;i<=r;i++){
            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) tmp[i]=p[l1++];
            else tmp[i]=p[l2++];
        }
        for (int i=l;i<=r;i++)
             p[i]=tmp[i];
    }
    int main(){
        scanf("%d",&n);scanf("%lf",&f[0]);
        for (int i=1;i<=n;i++){
            scanf("%lf%lf%lf",&p[i].a,&p[i].b,&p[i].rate);
            p[i].k=-p[i].a/p[i].b;
            p[i].id=i;
        }
        std::sort(p+1,p+1+n,cmp);
        cdq(1,n);
        printf("%.3lf",f[n]);
    }

     Splay代码

    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    const double eps=1e-8;
    int fa[2000005],ch[2000005][2];
    double lk[2000005],rk[2000005];
    double x[200005],y[200005],f[200005],rate[200005],a[200005],b[200005];
    int n,root;
    int read(){
        int t=0,f=1;char ch=getchar();
        while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
        while ('0'<=ch&&ch<='9'){t=t*10+ch-'0';ch=getchar();}
        return t*f;
    }
    void rotate(int x,int &rt){
        int y=fa[x],z=fa[y],l,r;
        if (ch[y][0]==x) l=0;else l=1;r=l^1;
        if (y!=rt){
            if (ch[z][0]==y) ch[z][0]=x;
                else ch[z][1]=x;
        }else rt=x;
        fa[x]=z;fa[y]=x;fa[ch[x][r]]=y;
        ch[y][l]=ch[x][r];ch[x][r]=y;
    }
    void splay(int x,int &rt){
        while (x!=rt){
            int y=fa[x],z=fa[y];
            if (y!=rt){
               if ((ch[y][0]==x)^(ch[z][0]==y)) rotate(x,rt);
               else rotate(y,rt);
            }
            rotate(x,rt);
        }
    }
    void insert(int &k,int Fa,int id){
         if (!k){
            k=id;
            fa[k]=Fa;
            return; 
         }
         if (x[k]+eps>=x[id]) insert(ch[k][0],k,id);
             else insert(ch[k][1],k,id);
    }
    double getk(int i,int j){
         if (fabs(x[i]-x[j])<eps) return -1e9;
         else return (y[i]-y[j])/(x[i]-x[j]);
    }
    int pre(int rt){
         int k=ch[rt][0];int tmp=k;
         while (k){
                if (lk[k]+eps>=getk(k,rt)) tmp=k,k=ch[k][1];
                else k=ch[k][0];
         }
         return tmp;
    }
    int suc(int rt){
         int k=ch[rt][1];int tmp=k;
         while (k){
                if (rk[k]<=eps+getk(k,rt)) tmp=k,k=ch[k][0];
                else k=ch[k][1];
         }
         return tmp;
    }
    void updata(int k){
         splay(k,root);
         if (ch[k][0]){
            int left=pre(root);
            splay(left,ch[k][0]);ch[left][1]=0;
            lk[k]=rk[left]=getk(k,left); 
         }else lk[k]=1e9;
         if (ch[k][1]){
            int right=suc(root);
            splay(right,ch[k][1]);ch[right][0]=0;
            lk[right]=rk[k]=getk(k,right);
         }else rk[k]=-1e9;
         if (lk[k]<=rk[k]+eps){
            root=ch[k][0];
            ch[root][1]=ch[k][1];
            fa[ch[k][1]]=root;
            fa[root]=0;
            rk[root]=lk[ch[k][1]]=getk(root,ch[k][1]);
         }
    }
    int find(int k,double slop){
        if (!k) return 0;
        if (lk[k]+eps>=slop&&slop+eps>=rk[k]){
            return k;
        }
        if (slop+eps>lk[k]) return find(ch[k][0],slop);
        else return find(ch[k][1],slop);
    }
    int main(){
        n=read();scanf("%lf",&f[0]);
        for (int i=1;i<=n;i++){
            scanf("%lf%lf%lf",&a[i],&b[i],&rate[i]);
        }
        for (int i=1;i<=n;i++){
            int j=find(root,-a[i]/b[i]);
            f[i]=std::max(f[i-1],x[j]*a[i]+b[i]*y[j]);
            y[i]=f[i]/(a[i]*rate[i]+b[i]);
            x[i]=y[i]*rate[i];
            insert(root,0,i);
            updata(i);
        }
        printf("%.3f
    ",f[n]);
    }
  • 相关阅读:
    Munge
    file upload custom form
    随笔摘要
    生成css 和 清缓存
    drupal commit 原则
    Git reset --hard
    www-data
    301/302的区别
    什么是request_uri
    in_array foreach array_search的性能比较
  • 原文地址:https://www.cnblogs.com/qzqzgfy/p/5665995.html
Copyright © 2020-2023  润新知