• Luogu4027 「NOI2007」货币兑换


    Solution

    推一下发现这个斜率优化不满足任何性质,那么平衡树维护凸包

    Code

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    #define reg register 
    #define For(i,a,b) for(reg int i=a;i<=b;++i) 
    #define Down(i,a,b) for(reg int i=a;i<=b;++i) 
    namespace yspm{
        inline int read()
        {
            int res=0,f=1; char k;
            while(!isdigit(k=getchar())) if(k=='-') f=-1;
            while(isdigit(k)) res=res*10+k-'0',k=getchar();
            return res*f;
        }
        const double inf=1e18+10,eps=1e-9;
        const int N=1e5+10;
        int n,st,rt;
        int ls[N],rs[N],fa[N];
        double a[N],b[N],rat[N],l[N],r[N],x[N],y[N],f[N];
        inline void rotate(int x)
        {
            int y=fa[x],z=fa[y];
            if(ls[z]==y) ls[z]=x; else rs[z]=x;
            if(ls[y]==x) ls[y]=rs[x],fa[rs[x]]=y,rs[x]=y;
            else rs[y]=ls[x],fa[ls[x]]=y,ls[x]=y;
            fa[y]=x; fa[x]=z;
            return ;
        }
        inline void splay(int x,int g)
        {
            while(fa[x]!=g)
            {
                int y=fa[x],z=fa[y]; 
                if(z!=g) rotate((ls[z]==y)^(ls[y]==x)?x:y);
                rotate(x);
            } if(!g) rt=x;
            return ;
        }
        inline int find(int x,double num) 
        {
            if(!x) return 0;
            if(l[x]+eps>=num&&r[x]<=num+eps) return x;
            if(l[x]<num+eps) return find(ls[x],num);
            return find(rs[x],num);    
        }  
        inline double calc(int p,int q)
        {
            if(fabs(x[p]-x[q])<eps) return -inf;
            return (y[p]-y[q])/(x[p]-x[q]);
        }
        inline int pre(int x)
        {
            int now=ls[x],res=now; 
            while(now)
            {
                if(l[now]+eps>=calc(now,x)) res=now,now=rs[now];
                else now=ls[now];
            } return res;
        }
        inline int nxt(int x) 
        {   
            int now=rs[x],res=now;
            while(now) 
            {
                if(r[now]<=eps+calc(now,x)) res=now,now=ls[now];
                else now=rs[now]; 
            } return res;
        }
        inline void del(int x)
        {
            rt=ls[x]; fa[rt]=0; fa[rs[x]]=rt; rs[rt]=rs[x]; 
            r[rt]=l[rs[x]]=calc(rt,rs[x]);
            return ; 
        }
        inline void work(int x)
        {
            splay(x,0);
            if(ls[x])
            {
                int p=pre(x); splay(p,x); rs[p]=0;
                r[ls[x]]=l[x]=calc(ls[x],x);
            }else l[x]=inf;
            if(rs[x])
            {
                int tmp=nxt(x); splay(tmp,x); ls[tmp]=0;
                l[rs[x]]=r[x]=calc(rs[x],x);
            }else r[x]=-inf;
            if(l[x]<=eps+r[x]) del(x);
            return ;
        }
        inline void insert(int &now,int fat,int id)
        {
            if(!now){now=id; fa[now]=fat; return ;}
            if(x[id]<=x[now]+eps) insert(ls[now],now,id); else insert(rs[now],now,id);
            return ;
        }
        signed main()
        {
            n=read(); scanf("%lf",&f[0]); 
            For(i,1,n)
            {
                scanf("%lf%lf%lf",&a[i],&b[i],&rat[i]);
                int pos=find(rt,-1.0*a[i]/b[i]);
                f[i]=max(f[i-1],x[pos]*a[i]+y[pos]*b[i]);
                y[i]=f[i]*1.0/(rat[i]*a[i]+b[i]); x[i]=rat[i]*y[i];
                insert(rt,0,i); work(i);
            } 
            printf("%.6lf
    ",f[n]);
            return 0;
        }
    }
    signed main(){return yspm::main();}
    
  • 相关阅读:
    Spark SQL 初步
    Android开展:ADT+Eclipse使用错误:Text editor does not have a document provider
    android 98 MediaPlayer+SurfaceView播放视频
    android97 播放音频 有进度条控制
    android96 内存创建图片副本,画画板
    Android记录6--ViewPage+Fragment的使用例子
    android95 缩放加载大图片
    android94 样式和主题
    android93 进程优先级补充
    android92 aidl远程进程通信
  • 原文地址:https://www.cnblogs.com/yspm/p/13626150.html
Copyright © 2020-2023  润新知