• luogu P4027 [NOI2007]货币兑换


    luogu

    ws**

    这里设(f_i)为前(i)天内得到的最多钱数,转移就考虑在第(i)天把钱变成券,然后枚举(>i)(j),在第(j)天换成钱,这里要算出第(i)天换的B券数量,直接写转移(f_j=max(f_{j-1},max_{i<j} frac{f_i}{a_ir_i+b_i}(a_jr_i+b_j)))

    考虑(frac{f_i}{a_ir_i+b_i}(a_jr_i+b_j) o f_j),先改成(frac{f_ir_i}{a_ir_i+b_i}*a_j+frac{f_i}{a_ir_i+b_i}*b_j o f_j),然后设(x_i=frac{f_ir_i}{a_ir_i+b_i},y_i=frac{f_i}{a_ir_i+b_i}),原式改写成(x_ia_j+y_ib_j o f_j)

    然后把(y_i)提出,得(y_i=-frac{a_j}{b_j}x_i+frac{1}{b_j}f_j),所以(f_j)可以看做是对于点((x_i,y_i)),用斜率(k=-frac{a_j}{b_j})去经过这个点,得到的最大的截距的(/b_i)的值.所以如果把前面的所有((x_i,y_i))的上凸壳搞出来,那截距最大的((x_i,y_i))会满足在它前面的点之间的线段斜率(>-frac{a_j}{b_j}),后面的线段斜率(le-frac{a_j}{b_j})(可以画图理解),那么维护好凸壳后就可以每次(O(logn))转移了.由于凸壳一定是由一些横坐标不相同的点依次排列形成,所以可以搞一个以横坐标为关键字的平衡树,每次把新的点插到对应位置,然后用叉积删掉这个点的不合法前驱后继,使得凸包没有凹下去的地方

    不想写平衡树可以写multiset,就是查询大概要两个log

    #include<bits/stdc++.h>
    #define LL long long
    #define db double
    
    using namespace std;
    const int N=1e5+10;
    const db eps=1e-10;
    int rd()
    {
        int x=0,w=1;char ch=0;
        while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+(ch^48);ch=getchar();}
        return x*w;
    }
    db f[N];
    struct node
    {
    	db x,y;
    	bool operator < (const node &bb) const {return x<bb.x;}
    	node operator - (const node &bb) const {return (node){x-bb.x,y-bb.y};}
    	db operator * (const node &bb) const {return x*bb.y-bb.x*y;}
    }nw;
    db K(node aa,node bb){return (bb.y-aa.y)/(bb.x-aa.x);}
    multiset<node> sb;
    multiset<node>::iterator it,nt,n2;
    int n;
    
    int main()
    {
        ///
    	n=rd(),f[1]=rd();
    	for(int i=1;i<=n;++i)
    	{
    		db a,b,c;
    		scanf("%lf%lf%lf",&a,&b,&c);
    		f[i]=max(f[i],f[i-1]);
    		if(!sb.empty())
    		{
    			it=sb.begin(),f[i]=max(f[i],((*it).y+(*it).x*a/b)*b);
    			it=--sb.end(),f[i]=max(f[i],((*it).y+(*it).x*a/b)*b);
    			db l=(*sb.begin()).x+eps,r=(*(--sb.end())).x-eps,ls=1e9;
    			while(r-l>eps&&r-l<ls)
    			{
    				ls=r-l;
    				db md=(l+r)/2;
    				it=sb.upper_bound((node){md,0});
    				if(it==sb.end()) break;
    				nt=--it,++it;
    				f[i]=max(f[i],max((*it).y+(*it).x*a/b,(*nt).y+(*nt).x*a/b)*b);
    				if(K(*it,*nt)>-a/b) l=(*it).x+eps;
    				else r=(*nt).x-eps;
    			}
    		}
    		nw=(node){f[i]/(a*c+b)*c,f[i]/(a*c+b)};
    		it=sb.insert(nw);
    		if(it!=sb.begin()&&it!=(--sb.end()))
    		{
    			nt=n2=it,--nt,++n2;
    			if(((*it)-(*nt))*((*n2)-(*it))>eps){sb.erase(it);continue;}
    		}
    		if(it!=sb.begin())
    		{
    			nt=it,--nt;
    			if(fabs((*it).x-(*nt).x)<eps)
    			{
    				if((*it).y<(*nt).y){sb.erase(it);continue;}
    				sb.erase(nt);
    			}
    		}
    		if(it!=(--sb.end()))
    		{
    			n2=it,++n2;
    			if(fabs((*it).x-(*n2).x)<eps)
    			{
    				if((*it).y<(*n2).y){sb.erase(it);continue;}
    				sb.erase(n2);
    			}
    		}
    		while(it!=sb.begin()&&it!=(++sb.begin()))
    		{
    			nt=it,--nt;
    			n2=nt,--n2;
    			if(((*nt)-(*it))*((*n2)-(*nt))>eps) break;
    			sb.erase(nt);
    		}
    		while(it!=(--sb.end())&&it!=(--(--sb.end())))
    		{
    			nt=it,++nt;
    			n2=nt,++n2;
    			if(((*nt)-(*it))*((*n2)-(*nt))<-eps) break;
    			sb.erase(nt);
    		}
    	}
    	printf("%.3lf
    ",f[n]);
    	return 0;
    }
    
  • 相关阅读:
    腾讯2面
    腾讯1面
    快手2面
    快手1面
    formData+ajax文件上传
    nginx限流&健康检查
    jvm crash分析
    Spring Cloud Gateway整合Eureka
    k8s-应用部署
    dockerfile-maven plugin自动镜像制作并发布
  • 原文地址:https://www.cnblogs.com/smyjr/p/12722456.html
Copyright © 2020-2023  润新知