【CF535E】Tavas and Pashmaks

题目

题目链接:https://codeforces.com/problemset/problem/535/E
\(n\) 个人,其中第 \(i\) 个人在一个单位时间内可以跑步 \(a_i\) 米,游泳 \(b_i\) 米。
我们称第 \(i\) 个人可能赢得比赛当且仅当存在正实数 \(A,B\) 满足 \(\frac{A}{a_i}+\frac{B}{b_i}\leq \min_{j\neq i}(\frac{A}{a_j}+\frac{B}{b_j})\)。求有多少人可能赢得比赛。
\(n\leq 2\times 10^5\)\(1\leq a_i,b_i\leq 10^4\)

思路

观察到对于两个人 \(i,j\),满足 \(a_i\leq a_j\)\(b_i\leq b_j\),那么第 \(i\) 个人不可能获胜(两个都相等的判一下就好了)。
所以可以按照 \(a\) 从大到小排序,把不可能获胜的扔掉后,\(b\) 一定严格递增,并且点数最多只有 \(10^4\) 个。
考虑第 \(i\) 个人获胜的前提:假设我们确定了第一个项目距离为 \(1\),那么为了比前 \(i-1\) 个人时间更短(\(a\) 已经降序了),可以算出第二个项目至少需要 \(\max\left(\frac{\frac{1}{a_i}-\frac{1}{a_j}}{\frac{1}{b_j}-\frac{1}{b_i}}\right)\) 米。
同理可以计算出如果第二个项目为 \(1\) 米,那么为了比后面的快,第一个项目所需要的距离。设这两个距离分别为 \(s_1,s_2\)
那么第 \(i\) 个人可能获胜当且仅当 \(s_1\times s_2\leq 1\)
直接 \(O(n^2)\) 跑就行了。

代码

#include <bits/stdc++.h>
#define mp make_pair
using namespace std;

const int N=200010;
const double eps=1e-8;
int n,m;
map<pair<int,int>,bool> v;

struct node
{
	int a,b;
}a[N],b[N];

bool cmp(node x,node y)
{
	if (x.a!=y.a) return x.a>y.a;
	return x.b>y.b;
}

int main()
{
	scanf("%d",&m);
	for (int i=1;i<=m;i++)
	{
		scanf("%d%d",&a[i].a,&a[i].b);
		b[i]=a[i];
	}
	sort(a+1,a+1+m,cmp);
	n=1;
	for (int i=2;i<=m;i++)
		if (a[i].a<a[n].a && a[i].b>a[n].b) a[++n]=a[i];
	for (int i=1;i<=n;i++)
	{
		if (i==1 || i==n) { v[mp(a[i].a,a[i].b)]=1; continue; }
		double mx1=0,mx2=0;
		for (int j=1;j<i;j++)
			mx1=max(mx1,(1.0/a[i].a-1.0/a[j].a)/(1.0/a[j].b-1.0/a[i].b));
		for (int j=n;j>i;j--)
			mx2=max(mx2,(1.0/a[i].b-1.0/a[j].b)/(1.0/a[j].a-1.0/a[i].a));
		if (mx1*mx2<1.0+eps) v[mp(a[i].a,a[i].b)]=1;
	}
	for (int i=1;i<=m;i++)
		if (v[mp(b[i].a,b[i].b)]==1) cout<<i<<" ";
	return 0;
}
posted @ 2021-10-08 09:01  stoorz  阅读(32)  评论(0编辑  收藏  举报