• $NOI2007$ 货币兑换


    \(NOI2007\)货币兑换

    辣鸡题目毁我青春

    刚看到这题的时候我一脸懵逼啊,问了一波\(fdf\)才把六十分推出来,然后强行理解了一波斜率和横坐标都不单调的斜率优化。理解了一下发现这不是傻逼题吗,然后我调斜率计算调到怀疑人生。

    \(Part1\) 关于斜率不存在

    这个很显然啊,但是我之前居然都没被卡过。

    根据两个点纵坐标来判断到底是返回\(inf\)还是\(-inf\)

    \(Part2\) 关于两点重合

    两点的纵坐标也相等时,是返回\(-inf\)的!别问我为什么浮点数比较用等于号是有用的,估计他们掉精度是有一个法则的吧,掉成一样的了。

    \(Part3\) 关于弹栈

    浮点数比较真的真的不要忽略等于号,在弹栈的时候,斜率相等的情况是要弹掉的,不然的话会\(WA\),感觉可能是二分的时候会挂掉,这个等于号是很有用的。(我记得凸包也不能有三点共线吧)

    挺裸的一道题,但是被上面的几个细节坑到了,积累一下,以后就不会出错了,挺好。

    下面是\(CDQ\)写法的代码。

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    #include<set>
    #include<queue>
    #include<map>
    #include<vector>
    #define N 101000
    #define EPS 1e-7
    #define ll long long
    #define RG register
    #define inf 1e18+1
    
    using namespace std;
    inline int read(){
        RG int x=0,o=1; RG char ch=getchar();
        while((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
        if(ch=='-') o=-1,ch=getchar();
        while(ch>='0'&&ch<='9') x=((x<<3)+(x<<1))+ch-'0',ch=getchar();
        return x*o;
    }
    
    int n,S,Q[N]; double f[N],a[N],b[N],r[N],ans;
    struct mona { int id; double K,A,B; } s[N],p[N];
    inline double Slope(const int &i,const int &j){
    	if(fabs(s[j].A-s[i].A)<EPS) return s[i].B<s[j].B?inf:-inf;
    	return (s[i].B-s[j].B)/(s[i].A-s[j].A);
    }
    
    inline void CDQ(int l,int r){
    	if(l==r){
    		f[l]=max(f[l],f[l-1]);
    		s[l].A*=f[l],s[l].B*=f[l]; return ;
    	}	int mid=l+r>>1;
    	CDQ(l,mid); RG int top=1; Q[1]=0;
    	for(RG int i=l;i<=mid;++i){
    		while(top>1&&Slope(Q[top-1],Q[top])<=Slope(Q[top-1],i)) --top;
    		Q[++top]=i;
    	}
    	for(RG int i=mid+1;i<=r;++i){
    		int L=2,R=top,ans=1;
    		while(L<=R){
    			int Mid=L+R>>1;
    			if(Slope(Q[Mid-1],Q[Mid])>s[i].K) L=Mid+1,ans=Mid;
    			else R=Mid-1;
    		}   f[i]=max(f[i],(-s[Q[ans]].A*s[i].K+s[Q[ans]].B)*b[i]);
    	}	CDQ(mid+1,r);
    	for(RG int l1=l,l2=mid+1,len=l;len<=r;++len)
    		if((s[l1].A<s[l2].A&&l1<=mid)||l2>r) p[len]=s[l1++];
    		else p[len]=s[l2++];
    	for(RG int i=l;i<=r;++i) s[i]=p[i];
    }
    
    int main(){
    	n=read(),S=read(),f[1]=S;
    	for(RG int i=1;i<=n;++i) scanf("%lf%lf%lf",&a[i],&b[i],&r[i]);
    	for(RG int i=1;i<=n;++i)
    		s[i]=(mona) { i,-a[i]/b[i],r[i]/(a[i]*r[i]+b[i]),1.0/(a[i]*r[i]+b[i]) };
    	CDQ(1,n); printf("%.3lf\n",f[n]);
    }
    
    
  • 相关阅读:
    记事本02
    助人快乐:笔记本连网
    高性能 架构实例 学习笔记
    食.运动.阅读
    The server name ... address could not be resolved
    Mysql 远程访问
    CSS布局 UI 学习笔记
    MySql 修改root密码
    C#:String类型中的CharAt 方法
    La_Lb_Lc
  • 原文地址:https://www.cnblogs.com/Lovemona/p/9805614.html
Copyright © 2020-2023  润新知