Practice.

A. Technical Support

题意

给定一个由 \(Q, A\) 组成的字符串,对于所有 \(Q\),判断在下一次 \(Q\) 出现或遍历到结束前,是否有至少一个 \(A\) 与之对应。

思路

如题,配对即可。

时间复杂度:\(O(n)\)

对应AC代码

#include <bits/stdc++.h>

using namespace std;

#define int long long
#define pii pair<int, int>

const int N = 2e5 + 10, inf = LONG_LONG_MAX, mod = 998244353;

signed main() {
    ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
    int q;
    cin >> q;
    while(q --){
        int n;
        cin >> n;
        string s;
        cin >> s;
        int cnt = 0;
        for(char e : s) {
            cnt += e == 'Q' ? 1 : -1;
            if(cnt < 0) cnt = 0;
        }
        cout << (cnt == 0 ? "Yes\n" : "No\n");
    }
}

别看错题((

B. Kevin and Permutation

题意

给定整数 \(n\),构建一个 \(n\) 的排列,使相邻数的差值的最小值最大。

思路

想要尽量让差值最大,那么我们只有相间地输出,或者说,若我们按 \(\frac{n}{2} + i, i\) 的规律输出,就可以让所有差值尽量相等。

可以贪心地认为上述的思路是正确的,解法不唯一。

时间复杂度:\(O(n)\)

对应AC代码

#include <bits/stdc++.h>

using namespace std;

#define int long long
#define pii pair<int, int>

const int N = 2e5 + 10, inf = LONG_LONG_MAX, mod = 998244353;

signed main() {
    ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
    int q;
    cin >> q;
    while(q --){
        int n;
        cin >> n;
        for(int i=1;i<=n/2;i++){
            cout << n / 2 + i << ' ' << i << ' ';
        }
        if(n % 2 == 1) cout << n;
        cout << '\n';
    }
}

找规律+乱贪.jpg

C1. Make Nonzero Sum (easy version)

详见C2,区别是C1给定的数组没有0

C2. Make Nonzero Sum (hard version)

题意

给定一个由 \(-1, 0, 1\) 构成的数组,将数组分为任意若干段,相邻两段的左段右边界和右段左边界相差 \(1\)。输出是否存在一种分段,将所有段相间赋上运算符号 \(+, -, +, - ,...\) 后,所有段的运算总和为 \(0\)。若存在,输出方案。

思路

首先,我们不考虑运算符号的时候,将所有数加起来会得到一个结果 \(ans\),若 \(ans = 0\),那么我们只需将所有单个元素单独成段就可以无视运算符号了。否则,因为考虑到加减是一样的,我们不妨来考虑 \(ans > 0\) 的情况:

显然,若要让 \(ans\) 减小,我们就只能让某一个 \(1\) 和左相邻的数组合为一段,那么,整个 \(ans\) 将会减少 \(2\)。可以发现,我们无法将 \(ans\) 减少奇数值,所以我们可以先判断 \(ans\) 的奇偶性。在运算的时候,需要变号的时候,变号的数一定但也只要让这个数位于某一段的偶数下标,所以,我们只需找两个相邻数,其中第一个数不需要变号,第二个数需要变号,那么将这两个数作为一段即可。

所以我们只需将 \(1\) 全部找出,判断能找出多少对上述相邻数,和 \(ans / 2\) 比较即可。

有趣的是,这种解法不用考虑是否包含 \(0\)

时间复杂度:\(O(n)\)

对应AC代码

#include <bits/stdc++.h>

using namespace std;

#define int long long
#define pii pair<int, int>

const int N = 2e5 + 10, inf = LONG_LONG_MAX, mod = 998244353;

int a[N];

signed main() {
    ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
    int q;
    cin >> q;
    while(q --){
        int n;
        cin >> n;
        int ans = 0;
        for(int i=1;i<=n;i++){
            cin >> a[i];
            ans += a[i];
        }
        if(abs(ans) % 2 == 1) cout << -1 << '\n';
        else{
            int r = 0;
            vector<pii> out;
            int left = ans / 2;
            if(left != 0) {
                int x = left / abs(left);
                r = 1;
                for (int i = 1; i < n; i++) {
                    if (a[i + 1] == x) {
                        out.emplace_back(i, i + 1);
                        r = i + 1;
                        i++;
                        left -= x;
                        if (left == 0) break;
                    } else {
                        out.emplace_back(i, i);
                        r = i;
                    }
                }
            }
            for(int i=r+1;i<=n;i++) out.emplace_back(i, i);
            if(left != 0) cout << -1 << '\n';
            else{
                cout << out.size() << '\n';
                for(auto e : out) cout << e.first << ' ' << e.second << '\n';
            }
        }
    }
}

想了半天不小心把两个难度一起做了((