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;
    }
  • 相关阅读:
    C# TCP异步服务/客户端
    Entity Framework Batch Update and Future Queries
    用c#编写socks代理服务器,大白话细述协议的最重要部分。
    ArraySegment AsEnumerable
    c#数据包拦截+网络编程
    为.Net Remoting增加基于SKYPE API的P2P传输通道
    如何看PDA的IP
    基本搞定PDA HTTP Server
    PDA SOAP Server探索历程(1)
    疑难问题之PDA SOAP Server
  • 原文地址:https://www.cnblogs.com/ctlchild/p/5187405.html
Copyright © 2011-2022 走看看