jzoj4640. 妖怪

题目描述

Description
在这里插入图片描述
Input
在这里插入图片描述
Output
在这里插入图片描述
Sample Input
3
1 1
1 2
2 2
Sample Output
8.0000
在这里插入图片描述
Data Constraint
在这里插入图片描述

10%

暴力乱搞

60%

二分答案,求每个怪物对应的x(a和b的转换比率)范围,判断是否合法

100%

并不是网上的做法
貌似都不加O3时跑得最快+代码最短
后来发现是水法


首先设比率为x(a/b=x),则贡献为ai+bi+ai/x+bi*x
显然后面的是一个对勾函数,图像大致如下
在这里插入图片描述
首先对于两个怪物ij,如果ai>aj且bi>bj,则j不会影响到答案
所以排序后用栈维护一下,把没用的筛掉
最后剩下的都是ai<aj且bi>bj(i<j)
也就是说j的开始位置比i突出,且j的后面那一段比i要缓
在这里插入图片描述
这时可以发现,最终的答案一定是排序后第n个函数和1~i-1中某个的交点或n的最小值!
在这里插入图片描述

-2019年5月17日
既然是水法就随便讲讲。。
把a最大的和其它函数相交,把x最小的交点和a最大的函数的最小值位置取min,然后求值
其实可以被hack掉

正解网上搜,大概类似斜率优化

code

#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define min(a,b) (a<b?a:b)
#define max(a,b) (a>b?a:b)
#define sqr(x) ((x)*(x))
#define Len 21000000
using namespace std;

struct type{
	long long a,b;
} a[1000001],d[1000001];
char ch[Len];
int n,N,i,j,k;
char *Ch=ch;
long double ans,s;

int get()
{
	int x=0;
	
	while (*Ch<'0' || *Ch>'9') *++Ch;
	while (*Ch>='0' && *Ch<='9') x=x*10+(*Ch-'0'),*++Ch;
	
	return x;
}

bool cmp(type a,type b)
{
	return a.a<b.a || a.a==b.a && a.b<b.b;
}

int main()
{
//	freopen("a.in","r",stdin);
//	freopen("monster2.in","r",stdin);
	
	fread(&ch,1,Len,stdin);
	
	n=get();
	fo(i,1,n)
	{
		a[i].a=get();
		a[i].b=get();
	}
	sort(a+1,a+n+1,cmp);
	
	fo(i,1,n)
	{
		while (N && d[N].b<=a[i].b) --N;
		d[++N]=a[i];
	}
	
	ans=sqrt((long double)d[N].a/d[N].b);
	fo(i,1,N-1)
	{
		s=(long double)(d[N].a-d[i].a)/(d[i].b-d[N].b);
		ans=min(ans,s);
	}
	
	printf("%0.4Lf\n",d[N].a+d[N].b+d[N].a/ans+d[N].b*ans);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值