Codeforces Round 840题解(A、B、C)

A. Absolute Maximization

我们可以选择两个位置i,j来存放最大值ai和最小值aj,对每一位,如果从a[1,n]的这一位有1,我们就可以把1挪到ai里,如果这意味有0,我们就可以把0挪到aj里,这样就可以构造出最大的ai和最小的aj

int n;
int a[550];

void solve() {
    cin >> n;
    for (int i = 1; i <= n; i ++) {
        cin >> a[i];
    }
    int max_v = 0, min_v = 1023;
    for (int r = 9; r >= 0; r --) {
        for (int i = 1; i <= n; i ++) {
            if (a[i] >> r & 1) {
                max_v |= 1 << r;
            }
            else {
                min_v &= ~(1 << r);
            }
        }
    }
    cout << max_v - min_v << '\n';
}

B. Incinerate

将怪物按照h从小到大排序,每次打出k的伤害就相当于把所有hi次伤害总和的怪物击倒。那么我们每次可以二分找出剩下的怪物的起始位置。

当某一次k降到0后,就不可能再打倒新的怪物,如果此时还没有把所有怪物都打倒的话,那么就不可能打倒所有的怪物了。

模拟这个过程,最坏情况是k每次都减一,因此时间复杂度最坏为klogn+nlogn

int n, k;
PII a[N];
int min_v[N];

void solve() {
    cin >> n >> k;
    for (int i = 1; i <= n; i ++) {
        cin >> a[i].first;
    }
    for (int i = 1; i <= n; i ++) {
        cin >> a[i].second;
    }
    sort(a + 1, a + 1 + n);
    min_v[n + 1] = INF;
    for (int i = n; i >= 1; i --) {
        min_v[i] = min(min_v[i + 1], a[i].second);
    }
//    for (int i = 1; i <= n; i ++) {
//        cout << min_v[i] << ' ';
//    }
//    cout << '\n';
    int cur = k;
    while (1) {
        int pos = lower_bound(a + 1, a + 1 + n, PII(cur + 1, 0)) - a - 1;
//        cout << pos << '\n';
        if (pos >= n) {
            cout << "YES" << '\n';
            return;
        }
        int cnt = k - min_v[pos + 1];
//        cout << cnt << '\n';
        cur += cnt;
        k = cnt;
        if (cnt <= 0) {
            cout << "NO" << '\n';
            return;
        }
    }
}

C. Another Array Problem

有点恶心的一道题,我最后15分钟才突然产生思路,但是分类有点小问题加没能调出来。。。结束后看分数,纳尼!竟然是2000分的题。。。

观察到如果最大值所在位置左边或者右边有2个元素,我们就可以把这个方向上所有元素都变成最大值。

例如:2,5,3,4 -> 2,5,1,1 -> 2,5,0,0 -> 2,5,5,5

实际上,如果最大值所在位置左边或右边有2个元素,我们可以把数组中所有元素都变成最大值。

例如:2,5,3,4 -> 2,5,5,5 -> 3,3,5,5 -> 0,0,5,5 -> 5,5,5,5

那么就只剩下两种特别情况了,当n=2时,只有两种方案,换或不换,直接输出比较即可。

n=3并且最大值在中间时比较恶心,我们注意到在换的过程中出现在最左边或者最右边的数都可以被用来覆盖整个数组。我们可以发现出现在左边的数最大是a[1]或者a[2]a[1],出现在右边的数最大是a[3]a[2]a[3],因为只要换一次,原本的最大值肯定就不保了,所以把这四个情况和不换的情况综合起来取max就是答案。但是如果要求具体详细严谨的证明,比较麻烦。蒟蒻想不出来,想出来也表达不清楚啊。。。

int n;
int a[M];

void solve() {
    cin >> n;
    int max_v = 0;
    for (int i = 1; i <= n; i ++) {
        cin >> a[i];
        max_v = max(max_v, a[i]);
    }
    vector<int> bag;
    for (int i = 1; i <= n; i ++) {
        if (a[i] == max_v) {
            bag.push_back(i);
        }
    }
    int ans = 0;
    for (int i = 1; i <= n; i ++) {
        ans += a[i];
    }
    if (n == 2) {
        cout << max(ans, abs(a[1] - a[2]) * 2) << '\n';
        return;
    }
    if (n >= 4) {
        cout << n * max_v << '\n';
        return;
    }
    if (a[1] == max_v || a[3] == max_v) {
        cout << n * max_v << '\n';
        return;
    }
    cout << max(ans, max({a[2] - a[1], a[2] - a[3], a[1], a[3]}) * 3) << '\n';
}
posted @   lightmon  阅读(16)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
点击右上角即可分享
微信分享提示