CF798D Mike and distribution

题目链接

解题思路

解法1:直接贪心

这题的直接贪心思路吗,是根据题目中的“选择 \(\lfloor\frac{n}{2}\rfloor+1\) 个”数,联想到按照 \(a_i\) 的值相邻的两两分组,取 \(b\) 更大的那一个。
这个思路很典。

解法2:没想到直接贪怎么办

然而,你可能没通过一些东西联想到解法1。
但是你容易发现一个事情,如果只考虑单一数组限制的话,随便乱取正确的概率应该都起码一半。
而同时满足两个数组的限制,我们感觉这样的概率应该也不小。

解法2——做法

于是我们随便乱取满 \(\lfloor\frac{n}{2}\rfloor+1\),看看是否合法。
重复上述过程做 \(1000\) 次。

解法2的步骤就是这么简单。

  • 一点有趣的东西:若要使得答案正确,这个随机次数在 \(n\leq 10^5\) 以内下限为 \(\sqrt n\) 量级。
    为什么,我也不知道。

代码实现

点击查看代码
#include <bits/stdc++.h>
#define FL(i, a, b) for (int i = (a); i <= (b); ++i)
#define FR(i, a, b) for (int i = (a); i >= (b); --i)
#define fi first
#define se second
using namespace std;
typedef long long ll;
constexpr int N = 1e5 + 10;
int n, id[N];
pair<int, int> p[N];
int main() {
    scanf("%d", &n);
    FL(i, 1, n) {
        scanf("%d", &p[i].fi);
    }
    FL(i, 1, n) {
        scanf("%d", &p[i].se);
    }
    FL(i, 1, n) {
        id[i] = i;
    }
    FL(T, 1, 1000) {
        random_shuffle(id + 1, id + n + 1);
        ll sx = 0, sy = 0;
        FL(i, 1, n / 2 + 1) {
            sx -= p[id[i]].fi;
            sy -= p[id[i]].se;
        }
        FL(i, n / 2 + 2, n) {
            sx += p[id[i]].fi;
            sy += p[id[i]].se;
        }
        if (sx < 0 && sy < 0) {
            printf("%d\n", n / 2 + 1);
            FL(i, 1, n / 2 + 1) {
                printf("%d%c", id[i], " \n"[i == n]);
            }
            break;
        }
    }
    return 0;
}
posted @ 2025-04-18 10:35  徐子洋  阅读(11)  评论(0)    收藏  举报