CF 798D Mike and distribution
题目链接:洛谷 CF 798D Mike and distribution CF 798D Mike and distribution
算法标签: 贪心
、思维
题目描述:
给两个长度为 \(n\) 的数列\(A,B\),要求至多选择 $\lfloor \frac{n}{2} \rfloor+1 $ 个下标,使得 \(A\) 数组中选出的数的和的两倍大于 \(sumA\) , \(B\) 数组中选出的数的和的两倍大于 \(sumB\)
题解:
贪心 + 思维!!!!
模拟赛T1,三个小时没有搞出正解 [擦汗.jpg]
既然题目中让我们最多选择 \(\lfloor \frac{n}{2} \rfloor+1\) ,并且没有要求最小,那么不妨我们就取 \(\lfloor \frac{n}{2} \rfloor+1\) 个值,显然这是对的(不要白不要啊……)。
之后我们考虑假如只有一个数列,这道题就变得很简单,排序之后找出前 \(\lfloor \frac{n}{2} \rfloor+1\) 个再判一下就可以。
那么对于两个数列怎么办???
现在我们来考虑这个神奇的 \(\lfloor \frac{n}{2} \rfloor+1\) ,本着给你就不白给的原则,我们会发现,这是什么
—— 两两分组再加一个
虽然很奇妙且扯皮淡雅,但是这的确是真的啊(考场上怎么可能 \(yy\) 出来???)
又因为排序可以处理两个数列中的一个,那么两两分组就可以处理第二个。 [肯定.jpg]
用结构体 \(node[~].a, node[~].b, node[~].id\) 存下来 \(A,B\) 数组和当前这对数在初始数列的位置。
首先按照数列\(A\)从大到小给结构体排序,我们就得到了一个 \(node[1].a \ge node[2].a \ge node[3].a \dots \ge node[n].a\) 的有序结构体,这样我们保证前 \(\lfloor \frac{n}{2} \rfloor+1\) 个\(A\)之和一定比剩下的\(A\)之和大。
之后我们假设先选择 \(node[1]\),之后对于后边的每一对值(两个值),选择其中 \(B\) 更大的一个,即对于\(node[2].b\),\(node[3].b\),选出更大的一个;对于 \(node[4].b,node[5].b\) ,选出更大的一个……
这时反观 \(A\) 的正确性,由于我们会发现 \(node[1].a \ge max(node[2].a, node[3].a),min(node[2].a, node[3].a) \ge max(node[4].a, node[5].a) \dots\)
所以现在 \(A\) 的正确性也是可以保证的。
之后就可以愉快的码代码了 !!! [开心.jpg]
AC代码
#include <bits/stdc++.h>
using namespace std;
#define setI(x) freopen(x".in", "r", stdin);
#define setO(x) freopen(x".out", "w", stdout);
#define setIO(x) setI(x) setO(x)
char *p1, *p2, buf[100000];
typedef long long ll;
#define nc() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2) ? EOF : *p1 ++ )
ll rd() {
ll x = 0, f = 1;
char c = nc();
while (c < 48) {
if (c == '-') {
f = -1;
}
c = nc();
}
while (c > 47) {
x = (((x << 2) + x) << 1) + (c ^ 48);
c = nc();
}
return x * f;
}
const int N = 100010;
typedef long long ll;
struct Node {
ll a, b;
int id;
} node[N];
bool cmp(Node A, Node B) {
if (A.a == B.a) {
return A.b > B.b;
}
return A.a > B.a;
}
int n;
int main() {
// setIO("game")
n = rd();
for (int i = 1; i <= n; i ++ ) {
node[i].a = rd();
node[i].id = i;
}
for (int i = 1; i <= n; i ++ ) {
node[i].b = rd();
}
sort(node + 1, node + 1 + n, cmp);
printf("%d\n", (n / 2) + 1);
printf("%d ", node[1].id);
for (int i = 2; i <= n; i += 2) {
ll nowb = node[i].b;
ll nxtb = node[i + 1].b;
if (nowb > nxtb) {
printf("%d ", node[i].id);
}
else {
printf("%d ", node[i + 1].id);
}
}
return 0;
}