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

    设$x_j$,$y_j$为第$j$天能买的A,B券数量,$f_i$为第$i$天的最大收益。$f_i=max_{1le j<i}a_ix_j+b_iy_j$,最大化$f_i$即找一个点$(x_j,y_j)$,使得这个点和斜率$-a_i/b_i$所确定的直线截距最大。平衡树维护凸包即可,按$x$建平衡树,并维护斜率单调递减,判断删点时用叉积比较优越。比一般的CDQ还快,可能是因为凸包的点数不多,所以平衡树的log就比较小。另外就是不加eps理论上也没有问题。

    #include<cstdio>
    #include<cstdlib>
    typedef double real;
    const int N=1e5+5;
    typedef struct node*ptr;
    struct node{
    	ptr i,j,s,t;real w,x,y;
    	node(){w=rand();}
    }*b,e[N];
    void zag(ptr&x){ptr y=x->j;x->j=y->i,y->i=x,x=y;}
    void zig(ptr&x){ptr y=x->i;x->i=y->j,y->j=x,x=y;}
    void ins(ptr y,ptr&x=b){
    	if(!x)x=y,x->s?x->s->t=x:0,x->t?x->t->s=x:0;
    	else if(y->x>x->x)
    		{ins(y,x->j);if(x->j->w>x->w)zag(x);}
    	else
    		{ins(y,x->i);if(x->i->w>x->w)zig(x);}
    }
    void del(ptr y,ptr&x=b){
    	if(y->x>x->x)del(y,x->j);
    	else if(x->x>y->x)del(y,x->i);
    	else if(!x->i)x=x->j;
    	else if(!x->j)x=x->i;
    	else if(x->i->w>x->j->w)zig(x),del(y,x->j);
    	else zag(x),del(y,x->i);
    }
    ptr pre(real k,ptr x=b){
    	ptr y=0;
    	while(x)k>=x->x?y=x,x=x->j:x=x->i;
    	return y;
    }
    ptr suc(real k,ptr x=b){
    	ptr y=0;
    	while(x)x->x>=k?y=x,x=x->i:x=x->j;
    	return y;
    }
    real slo(ptr s,ptr t){return(s->y-t->y)/(s->x-t->x);}
    real cal(ptr x,ptr s,ptr t){
    	real x1=x->x-s->x,x2=t->x-s->x;
    	real y1=x->y-s->y,y2=t->y-s->y;
    	return x1*y2-x2*y1;
    }
    void upd(ptr x){
    	if(ptr&y=x->s=pre(x->x))
    		while(y->s&&cal(x,y->s,y)<=0)
    			del(y),y=pre(x->x);
    	if(ptr&y=x->t=suc(x->x))
    		while(y->t&&cal(x,y,y->t)<=0)
    			del(y),y=suc(x->x);
    	if(!x->s||!x->t||cal(x->t,x->s,x)>0)
    		ins(x);
    }
    void eq2(real&x,real y){x=x<y?y:x;}
    real s,t,r,f;
    void sol(real k,ptr x=b){
    	if(x->s&&k>slo(x->s,x))sol(k,x->i);
    	else if(x->t&&slo(x,x->t)>k)sol(k,x->j);
    	else eq2(f,s*x->x+t*x->y);
    }
    int main(){
    	int n;
    	scanf("%d%lf",&n,&f);
    	for(int i=1;i<=n;++i){
    		scanf("%lf%lf%lf",&s,&t,&r);
    		if(i>1)sol(-s/t);
    		e[i].x=r*(e[i].y=f/(r*s+t));
    		upd(e+i);
    	}
    	printf("%.3f
    ",f);
    }
    
  • 相关阅读:
    python 的基础 学习 第六天 基础数据类型的操作方法 字典
    python 的基础 学习 第五天 基础数据类型的操作方法
    python 的基础 学习 第四天 基础数据类型
    ASP.NET MVC 入门8、ModelState与数据验证
    ASP.NET MVC 入门7、Hellper与数据的提交与绑定
    ASP.NET MVC 入门6、TempData
    ASP.NET MVC 入门5、View与ViewData
    ASP.NET MVC 入门4、Controller与Action
    ASP.NET MVC 入门3、Routing
    ASP.NET MVC 入门2、项目的目录结构与核心的DLL
  • 原文地址:https://www.cnblogs.com/f321dd/p/6113317.html
Copyright © 2011-2022 走看看