二八定律(优先队列+贪心)
描述
你听说过“二八定律”吗?经济学家发现,社会上80%的财富都被20%的人占据了,说明“少数有时候更重要”。
今天我们要做的题就和这个定律相关。给你一个长度为 n 的由非负整数构成的数列 A,你可以删除 0 个或任意多个元素,保持其余元素顺序不变,形成一个子序列 B。问你能否通过这样的方法得到一个长度至少为5的子序列 B,使得 B 的前 20% 项(向下取整)之和不小于 B 所有项之和的 80%?
换句话说,设 B 的长度为 k,B 的元素编号从 1 到 k ,则
你不需要真的构造出子序列 B。
输入
输入包含若干组样例,你需要处理到文件结束。
每组样例首先在一行中输入一个正整数 n 表示数列的长度(5≤ n ≤10⁵)。
随后在一行中给出 n 个非负整数 A₁, A₂, … , Aₙ (0≤ Aᵢ ≤10⁹, 1≤ i ≤n)。
保证所有样例中 n 的总和不超过10⁵。
输出
对于每一组样例,如果能构造出满足条件的子序列,在一行中输出"yes",否则在一行中输出"no"(不包括双引号)。
输入样例 1
6
8 0 4 0 1 1
6
1 2 2 4 8 8
输出样例 1
yes
no
代码
#include <iostream>
#include <vector>
#include <queue>
#define ll long long
using namespace std;
ll n, m, k, t, i, j;
int main() {
while (cin >> n) {
ll a[n + 1] = { 0 }, b[n + 1] = { 0 };
priority_queue<ll, vector<ll>, less<ll> >que;
for (i = 1; i <= n; i++)cin >> a[i], b[i] = max(b[i - 1], a[i]);
for (i = n, j = t = 0; i >= 2 && !t; i--) {
j += a[i]; que.push(a[i]);
if (que.size() > 4) {
j -= que.top();
que.pop();
}
t = (que.size() == 4 && b[i - 1] >= 4 * j);
}
cout << (t ? "yes" : "no") << endl;
}
return 0;
}