Codeforces Round 922 (Div. 2)

Codeforces Round 922 (Div. 2)

ps:25分钟AB都over,C给我打破防了、、、讨厌异或、、、我一直以为是数学结果、、、
只能说一怒之下怒了一下

A. Brick Wall

想法:要使得稳定性高,那么就多用1*2的砖块就行(A题可以直接找规律,通过样例)

#include <bits/stdc++.h>

using namespace std;

void solve() {
    int m, n;
    cin >> m >> n;
    cout << m * (int) (n / 2) << endl;
}

signed main() {
    int t;
    cin >> t;
    while (t--) {
        solve();
    }
}

B. Minimize Inversions

思路:他要求的是反转对数量最少,什么时候反转对数量会因为交换减少:将这个数本来有反转对到没有反转对,那么我们只看一个排列:很明显,当这个排列里面的反转对减少的时候,要么反转对总数减少,要么不变,所以我们就可以直接让他是反转对就行

#include <bits/stdc++.h>

using namespace std;

void solve() {
    int n;
    cin >> n;
    vector<pair<int, int>> a(n + 1);
    for (int i = 0; i < n; i++) {
        cin >> a[i].first;
    }
    for (int i = 0; i < n; i++) {
        cin >> a[i].second;
    }
    sort(a.rbegin(), a.rend());
    for (int i = n - 1; i >= 0; i--) {
        cout << a[i].first << " ";
    }
    cout << "\n";
    for (int i = n - 1; i >= 0; i--) {
        cout << a[i].second << " ";
    }
    cout << "\n";
}

int main() {
    int t;
    cin >> t;
    while (t--) {
        solve();
    }
}

C. XOR-distance

思路:这题就是求|(a⊕x)−(b⊕x)|的最小值,很明显他的最小值就是说这两个最靠近,这道题又是异或,那么就一位一位来看,假设ab这位相同,那么无论x为多少这位的运算结果都是0,我们要让x小,那么就是0。那么如果他们不一样,怎么判断是否应该有(如果都有的话,那么必为0),最大就是r,那么每次x的增加就应该有"r"的减少,以免x超过r

#include <bits/stdc++.h>

using namespace std;
#define int long long

void solve() {
    int a, b, r;
    cin >> a >> b >> r;
    bool h = true;
    int now = 0;
    for (int i = 60; i >= 0; i--) {
        int a1 = a >> i & 1;
        int b1 = b >> i & 1;
        if (b1 == a1) continue;
        if (h) {
            now = (1ll << i) * (a1 - b1);
            h = false;
        } else {
            if (r >= (1ll << i) && (a1 - b1) * now > 0) {
                r -= (1ll << i);
                now -= (a1 - b1) * (1ll << i);
            } else {
                now += (a1 - b1) * (1ll << i);
            }
        }
    }
    cout << abs(now) << endl;
}

signed main() {
    int t;
    cin >> t;
    while (t--) {
        solve();
    }
}

D. Blocking Elements

dp+二分

思路:将一个数组分割成x段,有x-1个分割点,找到这x-1个分割点使得每段的和和分割点和的最大值最小。首先我们要让该值最小,那么就来用二分来逼近这个值,很明显我们可以用单调队列来减少计算量,分割点的值就可以用dp来记录,还可以用一点点前缀和优化一下,只要分割点的值之和不大于想,以及这段之间的值不大于x就行

#include   <bits/stdc++.h>

using namespace std;
#define int long long
const int MAX = 1e5 + 10;
int a[MAX], s[MAX];
int n;

bool check(int x) {
    vector<int> dp(n + 2);
    priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> q;
    dp[1] = a[1];
    q.push({0, 0});//勿忘,反正是把我卡了亿下下
    for (int i = 1; i <= n + 1; i++) {
        if (a[i] > x) return false;
        while (q.size() && s[i - 1] - s[q.top().second] > x) q.pop();
        dp[i] = q.top().first + a[i];
        q.push({dp[i], i});
    }
    return (dp[n + 1] <= x);
}

void solve() {
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
        s[i] = a[i] + s[i - 1];
    }
    int l = 0, r = 1e16;
    a[n + 1] = 0;
    s[n + 1] = s[n];
    while (l < r) {
        int mid = (l + r) / 2;
        if (check(mid)) r = mid;
        else l = mid + 1;
    }
    cout << l << endl;
}

signed main() {
    int t;
    cin >> t;
    while (t--) {
        solve();
    }
}
posted @   goodluckbear  阅读(20)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示