Codeforces Round #575 (Div. 3)

比赛链接:https://codeforces.com/contest/1196

 A - Three Piles of Candies

题意

有 3 份糖果,Alice 先拿一份,Bob 后拿一份,最后 Alice 再拿一份,糖果较多的人要把多出来的分给另一个人,如果两个人都采取最优策略,Alice 最多能有多少个糖果。

题解

不管怎么取,Bob 一定可以拿到较少两份中的一份,也因此最多的一份一定是 Alice 的,所以 Alice 所拥有的糖果数一定比 Bob 多,答案即为 3 份平分后较少的一份。

代码

#include <bits/stdc++.h>
using namespace std;

void solve() {
    long long a, b, c; cin >> a >> b >> c;
    cout << (a + b + c) / 2 << "\n";
}

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

B - Odd Sum Segments

题意

将大小为 n 的数组分为 k 个和为奇数的区间,输出每个区间的右端点。(区间两两不相交且合并后为原数组)

题解

有解的情况:

  1. 至少有 k 个奇数
  2. 多出来的奇数个数为偶数

之后一个奇数一个右端点地划分 k - 1 个区间,第 k 个区间的右端点为 n 即可。

代码

#include <bits/stdc++.h>
using namespace std;

void solve() {
    int n, k; cin >> n >> k;
    long long a[n + 1] = {};
    int odd = 0;
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
        if (a[i] & 1) ++odd;
    } 
    if (k > odd or (odd - k) % 2 != 0) {
        cout << "NO" << "\n";
        return;
    }
    vector<int> ans;
    for (int i = 1; i <= n; i++) {
        if (a[i] & 1) ans.push_back(i);
    }
    ans.resize(k - 1);
    ans.push_back(n);
    cout << "YES" << "\n";
    for (auto i : ans) cout << i << ' ';
    cout << "\n";
}

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

C - Robot Breakout

题意

坐标系内有 n 个机器人,给出坐标及其能移动的方向(上下左右),找出一个所有机器人都能移动到的点。

题解

考虑到:

  • 如果一个机器人不能向左移动,此时它的 x 坐标即为最小的 x 坐标
  • 如果一个机器人不能向右移动,此时它的 x 坐标即为最大的 x 坐标
  • 如果一个机器人不能向上移动,此时它的 y 坐标即为最大的 y 坐标
  • 如果一个机器人不能向下移动,此时它的 y 坐标即为最小的 y 坐标

即记录最小最大的 x、y 坐标,答案即四者围成的矩形内的点。

代码

#include <bits/stdc++.h>
using namespace std;

const int INF = 1e5;

void solve() {
    int n; cin >> n;
    int mix = -INF, mxx = INF;
    int miy = -INF, mxy = INF;
    for (int i = 0; i < n; i++) {
        int x, y, l, u, r, d; cin >> x >> y >> l >> u >> r >> d;
        if (!l) mix = max(mix, x);
        if (!u) mxy = min(mxy, y);
        if (!r) mxx = min(mxx, x);
        if (!d) miy = max(miy, y);
    }
    if (mix <= mxx and miy <= mxy)
        cout << 1 << ' ' << mix << ' ' << miy << "\n";
    else
        cout << 0 << "\n";
}

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

D2 - RGB Substring (hard version)

题意

有一个由 'R', 'G', 'B' 组成的字符串 s 和无限字符串 "RGBRGB...",问至少要改变 s 中的多少个元素才能得到无限字符串的一个长为 k 的连续子串。 

题解

假设存在改变次数最少的长为 k 的连续子串,那么该连续子串一定是以 'R' 或 'G' 或 'B' 开头的,依次尝试将字符串 s 替换为以三者之一开头的无限字符串,记录替换次数最少的长为 k 的连续子串即可。

代码

#include <bits/stdc++.h>
using namespace std;

const string t = "RGB";

void solve() {
    int n, k; cin >> n >> k;
    string s; cin >> s;
    int ans = 1e9;
    for (int step = 0; step < 3; step++) {
        int res[n] = {};
        int cur = 0;
        for (int i = 0; i < n; i++) {
            res[i] = s[i] != t[(i + step) % 3];
            cur += res[i];
            if (i >= k) cur -= res[i - k];
            if (i >= k - 1) ans = min(ans, cur);
        }
    }
    cout << ans << "\n";
}

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

 

posted @ 2020-05-09 21:25  Kanoon  阅读(149)  评论(0)    收藏  举报