一道练手的题,思路很快就能出来,练习简化的用语言去实现
题目链接
两个人比赛,现在已经进行了 n n n轮,给定两行、每行 n n n个正整数作为每轮的分数,每人总分计算方法为,得分从大到小排前 n / 4 n/4 n/4个的和,接下来每轮每人可能得分为 x ( 0 < = x < = 100 ) x(0<=x<=100) x(0<=x<=100),问最小多少轮后第一个人分数高于第二个人
很容易想到用先排序再前缀和处理一下得分
如果第一个人总分小于第二个人
再思考如何分配后面的轮次
显然最差情况是再来
n
n
n轮,结果完全反过来,使得两人分数相等
思考发现,最优情况是,每轮让第一个人
+
100
+100
+100,第二个人
+
0
+0
+0
所以方法出来了,循环实现上述语句
发现直接模拟的话实现很麻烦,而且可能会
T
T
T掉
所以考虑每轮分数之间的关系
考虑第一个人,每次加
100
100
100分都会再减去被选中的分数中的最小值,所以总共第
k
k
k轮(补加的第
i
i
i轮)后第一个人的有效分数段数为
n
=
k
?
k
/
4
n=k-k/4
n=k?k/4,分数为
i
?
100
+
p
r
e
a
[
n
?
i
]
i*100+prea[n-i]
i?100+prea[n?i]
考虑第二个人,每次是加
0
0
0分,显然如果还有没有加上的分数会优先被加入总分,
当轮数大于有效分数的数量时,总分保持不变
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
bool cmp(int x, int y) {
return x > y;
}
void solve()
{
int n;cin >> n;
vector<int>a(n + 3), b(n + 3);
for (int i = 1;i <= n;i++)cin >> a[i];
for (int i = 1;i <= n;i++)cin >> b[i];
vector<ll>pa(n + 3), pb(n + 3);
sort(a.begin() + 1, a.begin() + 1 + n, cmp);
sort(b.begin() + 1, b.begin() + 1 + n, cmp);
pa[0] = 0;pb[0] = 0;
for (int i = 1;i <= n;i++)pa[i] = pa[i - 1] + a[i];
for (int i = 1;i <= n;i++)pb[i] = pb[i - 1] + b[i];
int ans = 0;
for (;;ans++) {
int k = n + ans;
int d = k - k / 4;
ll suma = 100 * ans + pa[d - ans];
ll sumb = d < n ? pb[d] : pb[n];
if (suma >= sumb) {
cout << ans << '\n';
return;
}
}
}
int main()
{
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int t;cin >> t;
while (t--) {
solve();
}
return 0;
}