[SCOI2016]妖怪

嘟嘟嘟


离NOI最后一周,把自己容易忘的知识点和板子复习一下。
(刚答完loj的笔试模拟,感觉上不了90……)
update:哦,我89……


先把式子写出来,每一个妖怪的战斗力\(S(i) = A + \frac{a}{b}D +D +\frac{b}{a}A\)
\(k = \frac{a}{b}\),于是\(S(i) = D *k + A *\frac{1}{k} +A +D\)
这东西是一个对勾函数,在第一象限是单峰的。我们要求的是一堆对勾函数的最大值的最小值。有一个结论是单峰函数复合起来还是单峰函数(但是我不会证啊),所以就可以三分了。


刚开始我直接傻呵呵的令\(L = 0, R = 1e10\),然后只得了10分。
应该把边界算准了:当\(D *k = A *\frac{1}{k}\)的时候,\(k = \sqrt{\frac{A}{D}}\),所以应该是\(1e-4 \sim 1e4\)
然后面向数据编程,我三分了115次才过掉这道题……

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<queue>
#include<vector>
#include<ctime>
#include<assert.h>
using namespace std;
#define enter puts("")
#define space putchar(' ')
#define Mem(a, x) memset(a, x, sizeof(a))
#define In inline
#define forE(i, x, y) for(int i = head[x], y; (y = e[i].to) && ~i; i = e[i].nxt)
typedef long long ll;
typedef double db;
const db INF = 1e18;
const db eps = 1e-10;
const int maxn = 1e6 + 5;
In ll read()
{
	ll ans = 0;
	char ch = getchar(), las = ' ';
	while(!isdigit(ch)) las = ch, ch = getchar();
	while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar();
	if(las == '-') ans = -ans;
	return ans;
}
In void write(ll x)
{
	if(x < 0) putchar('-'), x = -x;
	if(x >= 10) write(x / 10);
	putchar(x % 10 + '0');
}
In void MYFILE()
{
#ifndef mrclr
	freopen("monster.in", "r", stdin);
	freopen("ha.out", "w", stdout);
#endif
}

int n;
db A[maxn], D[maxn];

In db calc(db x)
{
	db ret = 0;
	for(int i = 1; i <= n; ++i) ret = max(ret, A[i] + D[i] + x * D[i] + 1.0 / x * A[i]);
	return ret;
}

int main()
{
//	MYFILE();
	n = read();
	for(int i = 1; i <= n; ++i) A[i] = read(), D[i] = read();
	db L = 1e-4, R = 1e4;
	for(int i = 1; i <= 115; ++i)
	{
		db mid1 = (L + R) * 0.5, mid2 = (mid1 + R) * 0.5;
		if(calc(mid1) < calc(mid2)) R = mid2;
		else L = mid1;
	}
	printf("%.4lf\n", min(calc(L), calc(R)));
	return 0;
}
posted @ 2019-07-06 20:56  mrclr  阅读(292)  评论(0编辑  收藏  举报