【YbtOJ高效进阶 贪心-4】国王游戏

链接

YbtOJ高效进阶 贪心-4

题目描述

现在有n人,每个人有一个左值和右值,他们排成一个序列,每个人的中值=排在他前面的所有人的左值乘积除以他自己的右值,现在你可以修改除了第一个人之外的人的位置,使得序列中最大中值最小

样例输入

3
1 1
2 3
7 4
4 6

样例输出

2

思路

考虑邻项交换

交换前 交换后
第i个人 \(\frac{S_{i-1}}{b_i}\) \(\frac{S_{i-1}}{b_{i+1}}\)
第i+1个人 \(\frac{S_{i-1} * a_i}{b_{i + 1}}\) \(\frac{S_{i-1}*a_{i+1}}{b_i}\)
那也就是比较式子大小就可以了

\[max(\frac{S_{i-1}}{b_i},\frac{S_{i-1} * a_i}{b_{i + 1}}) \ max(\frac{S_{i-1}}{b_{i+1}},\frac{S_{i-1}*a_{i+1}}{b_i}) \]

内部除以\(S_{i-1}\)
得到:

\[max(\frac{1}{b_i},\frac{a_i}{b_{i + 1}}) \ \ \ max(\frac{1}{b_{i+1}},\frac{a_{i+1}}{b_i}) \]

内部乘上\(b_i * b_{i+1}\),得

\[max(b_{i+1},a_i*b_i) \ \ \ max(b_{i},a_{i+1}{b_{i+1}}) \]

那很容易得到结论
若有\(i\)使得

\[a_i*b_i \geq a_{i+1} * b_{i+1} \]

那么我们就可以交换第\(i\)个人与第\(i+1\)个人
那么我们把所有人按\(a_i * b_i\)从小到大排序即可
别忘高精

代码

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#define ll long long

using namespace std;

ll n, kl, kr;

struct GJ
{
	ll l;
	ll a[10005];
}ans, S; 

struct qwq
{
	ll l, r;
	ll sum;
}a[10005];

bool cmp(qwq a, qwq b)
{
	return a.sum < b.sum;	
} 

GJ operator /(GJ x, int y)
{
	for(int i = x.l - 1; i >= 1; --i)
	{
		x.a[i - 1] += x.a[i] % y * 10;
		x.a[i] /= y;
		if(!x.a[i] && i == x.l - 1) x.l--;
	}
	x.a[0] = x.a[0] / y;
	return x;
}//高精除

GJ operator *(GJ x, int y)
{
	ll add = 0;
	for(int i = 0; i < x.l; ++i)
	{
		x.a[i] *= y;
		x.a[i] += add;
		add = x.a[i] / 10;
		x.a[i] %= 10;
	}
	x.a[x.l] += add;
	while(x.a[x.l])
	{
		x.l++;
		x.a[x.l] = x.a[x.l - 1] / 10;
		x.a[x.l - 1] %= 10;
	}
	return x;
}//高精乘

bool operator <(GJ x, GJ y)
{
	if(x.l != y.l) return x.l < y.l;
	for(int i = x.l - 1; i >= 0; --i)
		if(x.a[i] != y.a[i])
			return x.a[i] < y.a[i];
	
	return 0;
}

int main()
{
	scanf("%lld%lld%lld", &n, &kl, &kr);
	for(int i = 1; i <= n; ++i)
	{
		scanf("%lld%lld", &a[i].l, &a[i].r);
		a[i].sum = a[i].l * a[i].r;
	}
	sort(a + 1, a + n + 1, cmp);
	S.a[0] = kl; S.l = 1;
	for(int i = 1; i <= n; ++i)
	{
		if(ans < S / a[i].r) 
			ans = S / a[i].r;
		S = S * a[i].l;
	}
	printf("%lld", ans.a[ans.l - 1]);
	for(int i = ans.l - 2; i >= 0; --i) printf("%lld", ans.a[i]);
}
posted @ 2021-01-25 10:40  Aizx  阅读(65)  评论(0)    收藏  举报
Live2D