Codeforces Round 910 (Div. 2)(A-D)

A. Milica and String

分析:

给定一个只包含A和B的字符串,可以执行任意次操作:将前x个字符全部换为A或者B,问将字符串中经过最少次操作后使得字符串中含有B的数量等于给定的值k。

当字符串本来就刚好含有k个B则不需要操作,输出0即可,否则如果B多则可以找到一个位置,把前面全部替换成A,A多则找到一个位置将前面的全部换成B,次数最多为1,可以拿一个B的数量的前缀和记录,写起来就很方便。

code

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include
#define _CRT_SECURE_NO_WARNINGS
using namespace std;
#define int long long
typedef long long ll;
#define PII pair
#define endl '\n'
#define x first
#define y second
#define all(n) (n).begin() + 1,(n).end()
const int N = 1e5 + 5;
const int mod = 998244353;
void prvec(vector a) {
    for (auto i : a) cout << i << '|';
    cout << endl;
}
ostream& operator<<(ostream& ou, vector a) {
    for (int i = 0; i < a.size(); i++) ou << a[i] << ' ';
    return ou;
}
istream& operator>>(istream& in, vector& a) {
    for (int i = 1; i < a.size(); i++) in >> a[i];
    return in;
}
int gcd(int a, int b) {
    return b ? gcd(b, a % b) : a;
}
void solve() {
    int n, k; cin >> n >> k;
    string s; cin >> s;
    s = " " + s;
    vector pre(n + 1);
    for (int i = 1; i <= n; i++) pre[i] = pre[i - 1] + (s[i] == 'B');
    if (pre[n] == k) cout << 0 << endl;
    else if (pre[n] > k) {
        for (int i = 1; i <= n; i++) if (pre[i] ==pre[n] - k) return void(cout << 1 << endl << i << ' ' << 'A' << endl);
    }
    else {
        int dis = k - pre[n];
        for (int i = 1; i <= n; i++) if (i - pre[i] == dis)return void(cout << 1 << endl << i << ' ' << 'B' << endl);
    }
}
signed main() {
    ios::sync_with_stdio(0);
    cin.tie(0), cout.tie(0);
    int _ = 1; cin >> _;
    while (_--) solve();
}

B. Milena and Admirer

分析:

给定一个长度为n的整数数组a,可以执行任意次以下操作:

选择数组 a 中的元素 ai 和一个整数 x ,使得 1≤x

问将数组变为非递减所需的最小次数。

这道题一开始想歪了,很容易想到等量分配每一个数,实际上这样是错误的,比如4 13 6这三个数就不能这样,会变成4 7 6 6 再变为 4 3 4 6 6 最后是 2 2 3 4 6 6,显然没有 4 4 4 5 6 优,实际上题目已经提醒我们了,每一次操作数组的长度都会增长1,所以我们只要把逆序的大数分为均匀的x份使得每一份都恰好小于等于第二个数,这样一定是最优的,因为我们把它所有的数都分解到最大且小于等于后面那个数至少需要这么多次,那么我们要使得整体最优就一定要保证分解出来的最小数尽可能大,很容易得到均匀分配得到的最小数肯定是最大的,因此我们只需要从后往前扫描一遍同时更新这个位置分解出来的最小值即可。

code

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include
#define _CRT_SECURE_NO_WARNINGS
using namespace std;
#define int long long
typedef long long ll;
#define PII pair
#define endl '\n'
#define x first
#define y second
#define all(n) (n).begin() + 1,(n).end()
const int N = 1e5 + 5;
const int mod = 998244353;
void prvec(vector a) {
    for (auto i : a) cout << i << '|';
    cout << endl;
}
ostream& operator<<(ostream& ou, vector a) {
    for (int i = 0; i < a.size(); i++) ou << a[i] << ' ';
    return ou;
}
istream& operator>>(istream& in, vector& a) {
    for (int i = 1; i < a.size(); i++) in >> a[i];
    return in;
}
int gcd(int a, int b) {
    return b ? gcd(b, a % b) : a;
}
void solve() {
    int n; cin >> n;
    vector a(n + 1);
    cin >> a;
    int res = 0;
    for (int i = n - 1; i >= 1; i--) {
        int t = 0;
        if (a[i] > a[i + 1]) {
            res += (a[i] + a[i + 1] - 1) / a[i + 1]-1;//向上取整
            a[i] = a[i] / ((a[i] + a[i + 1] - 1) / a[i + 1]);
        }
    }
    cout << res << endl;
}
signed main() {
    ios::sync_with_stdio(0);
    cin.tie(0), cout.tie(0);
    int _ = 1; cin >> _;
    while (_--) solve();
}

C. Colorful Grid

分析:

Codeforces Round 910 (Div. 2)(A-D)_第1张图片

首先做这种题我们一定先想YES和NO的情况,最短路径一定是dx+dy(水平距离加垂直距离不绕路)等于m+n-2,如果k小于这个值,那么一定是NO,然后如果大于这个最短路,因为最后一定要回到(n,m)所以我们可以看成先到达(n,m)再走回来,根据对称性发现合法的情况一定是最短路径加上某个偶数,奇数一定是NO,接着刚刚的思路我们走到终点再走回来如果我们能构造出一个循环节使得我们可以在那儿消磨k的值不就成功了吗,所以我们像下面这样构造就好了

Codeforces Round 910 (Div. 2)(A-D)_第2张图片

其他地方可以随便染色,实现起来要注意一下细节就是在m为偶数和奇数时竖线的颜色应该反过来不然就会错乱,赛时就因为这个wa了。

code:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include
#define _CRT_SECURE_NO_WARNINGS
using namespace std;
#define int long long
typedef long long ll;
#define PII pair
#define endl '\n'
#define x first
#define y second
#define all(n) (n).begin() + 1,(n).end()
const int N = 1e5 + 5;
const int mod = 998244353;
void prvec(vector a) {
    for (auto i : a) cout << i << '|';
    cout << endl;
}
ostream& operator<<(ostream& ou, vector a) {
    for (int i = 0; i < a.size(); i++) ou << a[i] << ' ';
    return ou;
}
istream& operator>>(istream& in, vector& a) {
    for (int i = 1; i < a.size(); i++) in >> a[i];
    return in;
}
int gcd(int a, int b) {
    return b ? gcd(b, a % b) : a;
}
void solve() {
    int n, m, k;
    cin >> n >> m >> k;
    if (k < n + m - 2 || (k - n - m + 2) % 2) return void(cout << "NO" << endl);
    cout << "YES" << endl;
    for (int j = 1; j <= n; j++) {
        for (int i = 1; i <= m-1; i++) {
            if (i & 1) cout << 'R' << ' ';
            else cout << 'B' << ' ';
        }
        cout << endl;
    }
    if (m & 1) {
        for (int i = 0; i < n - 1; i++) {
            for (int j = 0; j < m; j++) if (i % 2 == 1 && j == m - 1) {
                cout << 'B' << " ";
            }
            else {
                cout << 'R' << " ";
            }
            cout << endl;
        }
    }
    else {
        for (int i = 0; i < n - 1; i++) {
            for (int j = 0; j < m; j++) if (i % 2 == 1 && j == m - 1) {
                cout << 'R' << " ";
            }
            else {
                cout << 'B' << " ";
            }
            cout << endl;
        }
    }
}
signed main() {
    ios::sync_with_stdio(0);
    cin.tie(0), cout.tie(0);
    int _ = 1; cin >> _;
    while (_--) solve();
}

D. Absolute Beauty

分析:

给定两个长度为n的数组a,b,定义Codeforces Round 910 (Div. 2)(A-D)_第3张图片

为这两个数组的美丽值,可以选择b数组中的两个数交换它们的位置,求这两个数组的美丽值的最大值,最多交换一次,可以不交换。我们把a_i >= b_i的下标i和a_i <= b_i的下标i分开来,然后我们分类讨论,选择交换的两个下标记为p,q

1)p,q都在第一个集合(a_i >= b_i):

——且 a_i >  a_j > b_i  >  b_j,那么对于原本的美丽值的贡献应该是 a_i - b_j + a_j - b_i - (a_i - b_i + a_j - b_j) = 0。

——且a_i > a_j   >  b_i  >  b_j,那么对于原本的美丽值的贡献应该是 a_i - b_j + a_j - b_i - (a_i - b_i + a_j - b_j) = 0。

——且a_i > b_i >  a_j  >  b_j,那么对于原本的美丽值的贡献应该是 a_i - b_j + b_i - a_j - (a_i - b_i + a_j - b_j) = 2(b_i - a_j)。

2)p,q都在第二个集合:

其实把a,b换一下就是第一个情况所以只有一种情况有意义就是 b_i > a_i > b_j > a_j 贡献为 2(a_i - b_j)。

3)p,q在两个集合

则 a_i>b_i  且 a_j< b_j 对原本的美丽值的贡献应该是2(a_i - a_j)或2(b_i - b_j)。具体的推演和上面类似。

因此我们只需要记录两个集合的a的最值和b的最值,然后根据上面的情况取max即可,需要注意的一点是,如果取max后是一个负值,那么说明无论怎样交换都一定是不优的,应该直接输出原本的美丽值

code:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include
#define _CRT_SECURE_NO_WARNINGS
using namespace std;
#define int long long
typedef long long ll;
#define PII pair
#define endl '\n'
#define x first
#define y second
#define all(n) (n).begin() + 1,(n).end()
const int N = 1e5 + 5;
const int mod = 998244353;
void prvec(vector a) {
    for (auto i : a) cout << i << '|';
    cout << endl;
}
ostream& operator<<(ostream& ou, vector a) {
    for (int i = 0; i < a.size(); i++) ou << a[i] << ' ';
    return ou;
}
istream& operator>>(istream& in, vector& a) {
    for (int i = 1; i < a.size(); i++) in >> a[i];
    return in;
}
int gcd(int a, int b) {
    return b ? gcd(b, a % b) : a;
}
void solve() {
    int n; cin >> n;
    vector a(n + 1);
    cin >> a;
    int res = 0;
    int mxa = -1, mna = 1e18, mxb = -1, mnb = 1e18;
    for (int i = 1; i <= n; i++) {
        int b; cin >> b;
        if (a[i] >= b) {
            mxa = max(mxa, b);
            mna = min(mna, a[i]);
        }
        else {
            mxb = max(mxb, a[i]);
            mnb = min(mnb, b);
        }
        res += abs(a[i] - b);
    }
    int add = max(max(mxa - mna, mxb - mnb), max(mxa - mnb, mxb - mna));
    if (add < 0) add = 0;
    cout << res + 2 * add << endl;
}
signed main() {
    ios::sync_with_stdio(0);
    cin.tie(0), cout.tie(0);
    int _ = 1; cin >> _;
    while (_--) solve();
}

你可能感兴趣的:(c++,算法)