zoukankan      html  css  js  c++  java
  • BZOJ1492: [NOI2007]货币兑换Cash

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

    f[i]=max(f[i-1],x[j]*a[i]+y[j]*b[i]) f[i]表示最大获利,x[j],y[j]分别表示第j天能够换到的最多的A,B券数量。

    在斜率优化中如果每个状态给的斜率是单调的,凸包上的点x坐标,y坐标都是单调的。。那上个单调队列就可以了。。

    这题中给的斜率和凸包上的点x坐标都不是单调的。。。

    (因为不会写平衡树维护动态凸包所以写了cdq分治。。

    其实。。。老老实实看论文比较好。。

    我就口胡几句吧TAT。。 先插入的点对后面的点有贡献。。如果能够使得凸包上的点x,y坐标有序,询问的区间斜率是有序的。那就可以维护个栈啊什么的吧。。

    于是先对斜率排序,按时间分成左右两个区间,左边区间暴力做出上凸包,右边区间询问。最后把两个区间按x,y合并起来(这样x,y坐标就有序辣)。。

    #include<cstring>
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<queue>
    #include<map>
    #include<cmath>
    #define rep(i,l,r) for (int i=l;i<=r;i++)
    #define down(i,l,r) for (int i=l;i>=r;i--)
    #define clr(x,y) memset(x,y,sizeof(x))
    #define maxn 100500
    #define inf int(1e9)
    #define ll long long
    #define eps 1e-9
    using namespace std;
    struct data{double k,a,b,x,y,r;int id;
    }a[maxn],t[maxn];
    int n,s[maxn];
    double f[maxn];
    int read(){
        int x=0,f=1; char ch=getchar();
        while (!isdigit(ch)){if (ch=='-') f=-1; ch=getchar();}
        while (isdigit(ch)){x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }   
    bool cmp(data a,data b){
        return a.k>b.k;
    }
    double getk(int A,int B)
    {
        if(!B)return -1e20;
        if(fabs(a[A].x-a[B].x)<eps)return 1e20;
        return (a[B].y-a[A].y)/(a[B].x-a[A].x);
    }
    int cross(data a,data b,data c){
        double x1=b.x-a.x,y1=b.y-a.y,x2=c.x-a.x,y2=c.y-a.y;
        if (fabs(x1*y2-x2*y1)<eps) return 0;
        if (x1*y2-x2*y1>0) return 1;
        return -1;
    }
    void cdq(int l,int r){
        if (l==r){
            f[l]=max(f[l],f[l-1]);
            a[l].y=f[l]/(a[l].a*a[l].r+a[l].b);
            a[l].x=a[l].r*a[l].y;
            return;
        }
        int l1=l,l2=(l+r)/2+1,mid=(l+r)/2,j=1;
        rep(i,l,r) if (a[i].id<=mid) t[l1++]=a[i]; else t[l2++]=a[i];
        rep(i,l,r) a[i]=t[i];
        cdq(l,mid);
        int top=0;
        rep(i,l,mid){
            while (top>1&&cross(a[s[top-1]],a[s[top]],a[i])>=0) top--;
            s[++top]=i;
        }
        s[++top]=0;
        rep(i,mid+1,r) {
            while (j<top&&getk(s[j],s[j+1])+eps>a[i].k) j++;
            int now=a[i].id;
            f[now]=max(f[now],a[i].a*a[s[j]].x+a[i].b*a[s[j]].y);
        }   
        cdq(mid+1,r);
        l1=l,l2=mid+1;
        rep(i,l,r) if (l1<=mid&&(a[l1].x<a[l2].x||(fabs(a[l1].x-a[l2].x)<eps&&a[l1].y<a[l2].y)||l2>r ) ) t[i]=a[l1++]; else t[i]=a[l2++];
        rep(i,l,r) a[i]=t[i];
    }
    int main(){
        n=read(); scanf("%lf",&f[0]);
        rep(i,1,n){
            scanf("%lf%lf%lf",&a[i].a,&a[i].b,&a[i].r); a[i].id=i;
            a[i].k=-a[i].a/a[i].b;
        }
        sort(a+1,a+1+n,cmp);
        cdq(1,n);
        printf("%.3lf
    ",f[n]);
        return 0;
    }
  • 相关阅读:
    Asp.net 动态添加Meta标签
    【转】在SharePoint Server 2010中更改“我的网站”
    SPQuery DateTime 类型查询
    Asp.net Web Application 打开 SharePoint 2010 Site 错误 The Web application at could not be found
    How To Create SharePoint 2010 Site Collection In Its Own DB
    C# 文件打印
    面试题 java集合
    《深入理解Java虚拟机》(六)堆内存使用分析,垃圾收集器 GC 日志解读
    《深入理解Java虚拟机》(五)JVM调优
    《深入理解Java虚拟机》(四)虚拟机性能监控与故障处理工具
  • 原文地址:https://www.cnblogs.com/ctlchild/p/5187405.html
Copyright © 2011-2022 走看看