zoukankan      html  css  js  c++  java
  • bzoj 3203 凸包+三分

    题目大意

    具体自己看吧link
    读入n,D,表示n关
    大概就是第i关有i只僵尸排成一队来打出题人
    最前面那只是编号为(i)的僵尸,最后面的一只是编号为(1)的僵尸
    最前面的僵尸离出题人(X_i)的距离,其它每只僵尸离前一只距离为固定值D
    僵尸平均每秒1米,植物每秒攻击力(y)
    植物连续攻击,可以当它激光,打死前一只瞬间就可以开始打后一只
    对于每一关,我们要选择一个尽可能小的y,保证出题人不被打死
    求y总和最小为多少

    分析

    我们考虑(y)要满足什么条件
    首先要打死每只僵尸,极限是在它到出题人跟前时把它打死
    这时我们总共攻击了(dist*y)的血量,打掉了那只僵尸的前缀和血量
    (y_i=max{frac {sum[i]-sum[j-1]} {x[i]+(i-j)*d}})(i可以等于j)
    转化为斜率形式
    y2=sum[i], y1=sum[j-1]
    x2=x[i]+id, x1=jd
    将(x1,y1)用凸包维护一个下凸壳
    用(x2,y2)在凸包上三分找到一个斜率最大的点

    solution

    #include <cstdio>
    #include <cstdlib>
    #include <cstdlib>
    #include <cctype>
    #include <cmath>
    #include <algorithm>
    using namespace std;
    typedef long long LL;
    typedef long double db;
    const int M=100007;
    
    inline LL rd(){
    	LL x=0;bool f=1;char c=getchar();
    	for(;!isdigit(c);c=getchar()) if(c=='-') f=0;
    	for(;isdigit(c);c=getchar()) x=x*10+c-48;
    	return f?x:-x;
    }
    
    int n;
    db ans;
    LL D,sum[M],bg[M];
    
    struct pt{
    	db x,y;
    	pt(db xx=0,db yy=0){
    		x=xx; y=yy;
    	}
    }stack[M];  int tot;
    
    pt operator -(pt x,pt y){return pt(x.x-y.x,x.y-y.y);}
    db operator ^(pt x,pt y){return x.x*y.x-x.y*y.y;}
    db operator *(pt x,pt y){return x.x*y.y-y.x*x.y;}
    
    db side(pt x,pt y,pt z){return (y-x)*(z-x);}
    db slop(pt x,pt y){pt tp=y-x;return tp.y/tp.x;}
    
    
    void ins(pt x){
    	while(tot>1&&side(stack[tot-1],stack[tot],x)<0) tot--;
    	stack[++tot]=x;
    }
    
    db get(pt x){
    	int l=1,r=tot,m1,m2,le;
    	db d1,d2;
    	while(l+1<r){
    		le=(r-l+1)/3;
    		m1=l+le-1;
    		m2=m1+le;
    		d1=slop(stack[m1],x);
    		d2=slop(stack[m2],x);
    		if(d1<d2) l=m1+1;
    		else r=m2-1;
    	}
    	return max(slop(stack[l],x),slop(stack[r],x));
    }
    
    int main(){
    	int i;
    	n=rd(),D=rd();
    	for(i=1;i<=n;i++){
    		sum[i]=sum[i-1]+rd();
    		bg[i]=rd();
    	}
    	pt nw;
    	for(i=1;i<=n;i++){
    		nw=pt(i*D,sum[i-1]);
    		ins(nw);
    		nw=pt(bg[i]+i*D,sum[i]);
    		ans+=get(nw);
    	}
    	printf("%.0Lf
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    BootStrap 智能表单系列 五 表单依赖插件处理
    BootStrap 智能表单系列 四 表单布局介绍
    BootStrap 智能表单系列 三 分块表单配置的介绍
    LinQ.OrderBy 多个字段排序
    ABP.NET CORE 遇到的小问题
    vs2017断点无效 当前不会命中断点 已设置断点单还未绑定
    DateTime 取年月日;字符串截取
    C# DateTime 多个时间段循环相加;两个时间段求差值
    ABP.Net Core 小白使用教程 附件:ABP.NET中文文档
    ASP.NET MVC+Easyui 后台管理系统的图片上传
  • 原文地址:https://www.cnblogs.com/acha/p/6427369.html
Copyright © 2011-2022 走看看