Codeforces Round 877 (Div.2) 题解 A - D

A. Blackboard List

题目大意

起初黑板上有两个数,现在不断选取两个数作出他们俩差的绝对值并写在黑板上,如此往复直到黑板上有 \(n\) 个数。现在给定这 \(n\) 个数,问起初两数的其中一个数是多少。

解题思路

我们分两种可能:要么这两个数有负数,要么没有。

  1. 有负数的情况,因为每次写下的都是绝对值,那么这些数中的负数一定是起初两数之一。
  2. 没有负数的情况,没有负数可以保证每次的差值一定比原来两数的最大值要小,因为最小情况下也是减去 \(0\),得到的结果不会比原数大。那么全部数的最大值就是原来两数的最大值。

AC Code

#include <iostream>
#include <algorithm>
#include <cstring>
#define endl '\n'
#define ios ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr)
using namespace std;
typedef long long LL;

const int N = 1e5 + 10;
const int MOD = 1e9 + 7;

void solve() {
    LL n, x;
    cin >> n;
    LL min_ = 0x3f3f3f3f, max_ = -0x3f3f3f3f;
    for (int i = 1; i <= n; ++i) {
        cin >> x;
        min_ = min(min_, x);
        max_ = max(max_, x);
    }
    cout << (min_ < 0 ? min_ : max_) << endl;
}

signed main() {
    ios;
    int T = 1;
    cin >> T;
    while (T--) {
        solve();
    }
}

B. Minimize Permutation Subarrays

题目大意

给定 \(1\sim n\) 的一个排列,现在我们只允许做一次交换,使得交换后的排列的所有子数列中的排列数最少。

这里排列指的是数组中恰好有 \(1,2,\dots,subarray.\text{length}\) 这些数.

解题思路

我们的排列一定是 \(1, 2,\dots\) 这样的,我们只需要阻断 \(1\)\(2\),并且塞进去最不可能出现在这里元素 \(n\) 即可。这时我们的子数组中的排列就只有两个,单独的 \(1\) 和整个排列。

AC Code

#include <iostream>
#include <algorithm>
#include <cstring>
#define endl '\n'
#define ios ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr)
using namespace std;
typedef long long LL;

const int N = 1e6 + 10;
const int MOD = 998244353;

int a[N];

void solve() {
    int n;
    cin >> n;
    for (int i = 1; i <= n; ++i) {
        int x;
        cin >> x;
        a[x] = i;
    }
    if ((a[n] - a[1]) * (a[n] - a[2]) < 0) {
        cout << 1 << ' ' << 1 << endl;
    } else if (a[n] > a[1] && a[n] > a[2]) {
        cout << a[n] << ' ' << max(a[1], a[2]) << endl;
    } else {
        cout << a[n] << ' ' << min(a[1], a[2]) << endl;
    }
}

signed main() {
    ios;
    int T = 1;
    cin >> T;
    while (T--) {
        solve();
    }
}

C. No Prime Differences

题目大意

需要构造一个 \(n\times m\) 的矩阵,需要满足其中的元素恰好为 \(1\sim nm\),同时任意相邻两项的差的绝对值不为质数。

解题思路

相邻两项无非就是横着俩以及竖着俩都满足差值不是质数。我们可以考虑构造差值满足以下关系:

  1. 差值为 \(1\)
  2. 差值为 \(2\) 的非一次倍。
  3. 差值为 \(n\) 的整数倍。

如果 \(n\) 是偶数的话,那么很容易看出来,只需要按照如下情形即可:

 1  2  3  4  5  6  7  8
 9 10 11 12 13 14 15 16
17 18 19 20 21 22 23 24

如果 \(n\) 是奇数的话,我们可以调换输出顺序,把偶数行先输出,奇数行后输出:

 6  7  8  9 10
16 17 18 19 20
 1  2  3  4  5
11 12 13 14 15

奇数行和偶数行内部满足上面对 \(n\) 为偶数情况的讨论,两者交界处的差值是 \(n\) 的整数倍非质数,故可如此构造。

AC Code

#include <iostream>
#include <algorithm>
#include <cstring>
#define endl '\n'
#define ios ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr)
using namespace std;
typedef long long LL;

const int N = 1e6 + 10;
const int MOD = 998244353;

void solve() {
    int n, m;
    cin >> n >> m;
    for (int i = 1; i < n; i += 2) {
        for (int j = 1; j <= m; ++j) {
            cout << i * m + j << ' ';
        }
        cout << endl;
    }
    for (int i = 0; i < n; i += 2) {
        for (int j = 1; j <= m; ++j) {
            cout << i * m + j << ' ';
        }
        cout << endl;
    }
    cout << endl;
}

signed main() {
    ios;
    int T = 1;
    cin >> T;
    while (T--) {
        solve();
    }
}

D. Bracket Walk

题目大意

给定一个括号序列,起初时人站在第一个字符上面,每次可以向左或者向右走。同时给定 \(q\) 个询问,每次询问会将括号序列第 \(x\) 个括号倒转方向,问能否使得走到的字符拼接起来成为一个匹配的括号序列。

解题思路

首先确定一定不可能的情况,我们向左走一次,就必须向右走回来,所以最终步数的奇偶性和 \(n\) 一致,所以 \(n\) 为奇数的时候肯定不能组成匹配的括号序列。

我们考虑原串已经含有了 (),那么可以直接走过这两个字符,如果出现不匹配部分,我们就将多走一次少的那种括号,我们期望获得 ()() 这样的括号序列,那么可以记录有多少括号不满足这一条,存到我们的set中,随后针对翻转修改,我们通过修改set的元素就可以达到组件的删改,最后只需要判断set的头元素和尾元素,实际上就是最大最小值的奇偶关系即可。

AC Code

#include <iostream>
#include <algorithm>
#include <cstring>
#include <set>
#define endl '\n'
#define ios ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr)
using namespace std;
typedef long long LL;

const int N = 1e6 + 10;
const int MOD = 998244353;

set<LL> st;

void solve() {
    int n, m;
    cin >> n >> m;
    string s;
    cin >> s;
    for (int i = 0; i < n; ++i) {
        if (s[i] == (i & 1 ? '(' : ')')) {
            st.insert(i + 1);
        }
    }
    while (m--) {
        int x;
        cin >> x;
        if (st.contains(x)) {
            st.erase(x);
        } else {
            st.insert(x);
        }
        cout << (n & 1 || (!st.empty() && (*st.begin() & 1 || !(*st.rbegin() & 1))) ? "NO" : "YES") << endl;
    }
}

signed main() {
    ios;
    int T = 1;
//    cin >> T;
    while (T--) {
        solve();
    }
}
posted @ 2023-06-12 18:19  叁纔  阅读(36)  评论(0编辑  收藏  举报