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

    题解:斜率优化DP

    用平衡树维护凸包

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    using namespace std;
    const int maxn=200009;
    const int oo=1000000000;
    const double eps=1e-9;
    
    int dcmp(double x){
    	if(fabs(x)<eps)return 0;
    	if(x>0)return 1;
    	else return -1;
    }
    
    int n;
    double A[maxn],B[maxn],R[maxn],f[maxn];
    double Getx(int i){
    	return f[i]*R[i]/(R[i]*A[i]+B[i]);
    }
    double Gety(int i){
    	return f[i]/(R[i]*A[i]+B[i]);
    }
    double GetK(int i,int j){
    	double xi=Getx(i),yi=Gety(i);
    	double xj=Getx(j),yj=Gety(j);
    	return (yi-yj)/(xi-xj);
    }
    
    int nn=0,root=0;
    int fa[maxn]={0},ch[maxn][2]={0};
    double lk[maxn],rk[maxn];
    
    int son(int x){
    	if(ch[fa[x]][0]==x)return 0;
    	else return 1;
    }
    
    void Rotate(int x){
    	int y=fa[x];
    	int z=fa[y];
    	int b=son(x),c=son(y);
    	int a=ch[x][b^1];
    	if(z)ch[z][c]=x;
    	else root=x;
    	fa[x]=z;
    	if(a)fa[a]=y;
    	ch[y][b]=a;
    	fa[y]=x;ch[x][b^1]=y;
    }
    
    void Splay(int x,int i){
    	while(fa[x]!=i){
    		int y=fa[x];
    		int z=fa[y];
    		if(z==i){
    			Rotate(x);
    		}else{
    			if(son(x)==son(y)){
    				Rotate(y);Rotate(x);
    			}else{
    				Rotate(x);Rotate(x);
    			}
    		}
    	}
    }
    
    void Del(){
    	int x=root;
    	if((!ch[x][0])&&(!ch[x][1])){
    		root=0;
    	}else if(!ch[x][0]){
    		root=ch[x][1];
    		fa[ch[x][1]]=0;
    		lk[ch[x][1]]=oo;
    	}else if(!ch[x][1]){
    		root=ch[x][0];
    		fa[ch[x][0]]=0;
    		rk[ch[x][0]]=-oo;
    	}else{
    		int pre=ch[x][0];
    		int suc=ch[x][1];
    		while(ch[pre][1])pre=ch[pre][1];
    		while(ch[suc][0])suc=ch[suc][0];
    		Splay(pre,x);Splay(suc,x);
    		ch[pre][1]=suc;fa[suc]=pre;
    		root=pre;fa[pre]=0;
    		rk[pre]=lk[suc]=GetK(pre,suc);
    	}
    }
    
    void Ins(int p){
    	double xp=Getx(p);
    	int x=root,y=0;
    //	cout<<"inseting"<<endl;
    	while(x){
    		y=x;
    		double xi=Getx(x);
    		if(dcmp(xi-xp)==0){
    			if(dcmp(Gety(x)-Gety(p))>=0){
    				return;
    			}else{
    				Splay(x,0);Del();Ins(p);return;
    			}
    		}
    		if(xp>xi)x=ch[x][1];
    		else x=ch[x][0];
    	}
    //	cout<<"endinseting"<<endl;
    	fa[x=p]=y;
    	if(!y){
    		root=x;
    	}else{
    		if(Getx(x)>Getx(y))ch[y][1]=x;
    		else ch[y][0]=x;
    	}
    	Splay(x,0);
    	int pre=ch[x][0];
    	while(ch[pre][1])pre=ch[pre][1];
    	int suc=ch[x][1];
    	while(ch[suc][0])suc=ch[suc][0];
    	if(!pre)lk[x]=oo;
    	else lk[x]=rk[pre]=GetK(x,pre);
    	if(!suc)rk[x]=-oo;
    	else rk[x]=lk[suc]=GetK(x,suc);
    }
    
    void QueryK(double k){
    	int x=root;
    	while(x){
    		if(lk[x]>=k&&rk[x]<=k){
    			Splay(x,0);return;
    		}else if(rk[x]>=k){
    			if(ch[x][1]){
    				x=ch[x][1];
    			}else{
    				Splay(x,0);return;
    			}
    		}else{
    			if(ch[x][0]){
    				x=ch[x][0];
    			}else{
    				Splay(x,0);return;
    			}
    		}
    	}
    }
    
    void Getrk(int x,int p){
    	int y=0;
    	while(x){
    		if(dcmp(lk[x]-GetK(x,p)>=0)){
    			y=x;x=ch[x][1];
    		}else{
    			x=ch[x][0];
    		}
    	}
    	if(y==0)return;
    	Splay(y,p);
    	ch[y][1]=0;
    	rk[y]=lk[p]=GetK(y,p);
    }
    void Getlk(int x,int p){
    	int y=0;
    	while(x){
    		if(dcmp(rk[x]-GetK(x,p))<=0){
    			y=x;x=ch[x][0];
    		}else{
    			x=ch[x][1];
    		}
    	}
    	if(y==0)return;
    	Splay(y,p);
    	ch[y][0]=0;
    	rk[p]=lk[y]=GetK(y,p);
    }
    
    int main(){
    	scanf("%d%lf",&n,&f[0]);
    	for(int i=1;i<=n;++i)scanf("%lf%lf%lf",&A[i],&B[i],&R[i]);
    	
    	for(int i=1;i<=n;++i){
    		double k;
    		if(dcmp(B[i])==0)k=-oo;
    		else k=-A[i]/B[i];
    		
    		f[i]=f[i-1];
    		QueryK(k);
    		if(root)f[i]=max(f[i],(A[i]*Getx(root)+B[i]*Gety(root)));
    		
    		Ins(i);
    		if(root!=i)continue;
    		if(lk[i]<rk[i]){
    			Del();
    		}else{
    			if(ch[i][0]){
    				Getrk(ch[i][0],i);
    			}
    			if(ch[i][1]){
    				Getlk(ch[i][1],i);
    			}
    		}
    	}
    	
    	printf("%.3f
    ",f[n]);
    	return 0;
    }
    

      

    自己还是太辣鸡了
  • 相关阅读:
    【NX二次开发】获取体是实体还是片体UF_MODL_ask_body_type()
    【creo】CREO5.0+VS2019配置(还没写完)
    【NX二次开发】导出x_t、导入x_t例子,UF_PS_export_data、UF_PS_import_data
    UG_PS Parasolid相关的操作
    【NX二次开发】创建老版的基准平面uf5374
    UnityShader之固定管线命令Combine纹理混合【Shader资料4】
    UnityShader之固定管线Fixed Function Shader【Shader资料3】
    UnityShader之Shader分类篇【Shader资料2】
    UnityShader之Shader格式篇【Shader资料1】
    Unity3D事件函数的执行顺序
  • 原文地址:https://www.cnblogs.com/zzyer/p/8548546.html
Copyright © 2011-2022 走看看