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

链接

YbtOJ高效进阶 贪心-4

题目描述

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

样例输入

3
1 1
2 3
7 4
4 6

样例输出

2

思路

考虑邻项交换

交换前 交换后
第i个人 S i − 1 b i \frac{S_{i-1}}{b_i} biSi1 S i − 1 b i + 1 \frac{S_{i-1}}{b_{i+1}} bi+1Si1
第i+1个人 S i − 1 ∗ a i b i + 1 \frac{S_{i-1} * a_i}{b_{i + 1}} bi+1Si1ai S i − 1 ∗ a i + 1 b i \frac{S_{i-1}*a_{i+1}}{b_i} biSi1ai+1

那也就是比较式子大小就可以了
m a x ( S i − 1 b i , S i − 1 ∗ a i b i + 1 )   m a x ( S i − 1 b i + 1 , 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}) max(biSi1,bi+1Si1ai) max(bi+1Si1,biSi1ai+1)
内部除以 S i − 1 S_{i-1} Si1
得到:
m a x ( 1 b i , a i b i + 1 )     m a x ( 1 b i + 1 , a i + 1 b i ) max(\frac{1}{b_i},\frac{a_i}{b_{i + 1}}) \ \ \ max(\frac{1}{b_{i+1}},\frac{a_{i+1}}{b_i}) max(bi1,bi+1ai)   max(bi+11,biai+1)
内部乘上 b i ∗ b i + 1 b_i * b_{i+1} bibi+1,得
m a x ( b i + 1 , a i ∗ b i )     m a x ( b i , a i + 1 b i + 1 ) max(b_{i+1},a_i*b_i) \ \ \ max(b_{i},a_{i+1}{b_{i+1}}) max(bi+1,aibi)   max(bi,ai+1bi+1)
那很容易得到结论
若有 i i i使得 a i ∗ b i ≥ a i + 1 ∗ b i + 1 a_i*b_i \geq a_{i+1} * b_{i+1} aibiai+1bi+1
那么我们就可以交换第 i i i个人与第 i + 1 i+1 i+1个人
那么我们把所有人按 a i ∗ b i a_i * b_i aibi从小到大排序即可
别忘高精

代码

#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]);
}

猜你喜欢

转载自blog.csdn.net/LTH060226/article/details/112131589