A. 123233

模拟

代码实现
#include <bits/stdc++.h>

using namespace std;

int main() {
    string s;
    cin >> s;
    
    ranges::sort(s);
    
    if (s == "122333") puts("Yes");
    else puts("No");
    
    return 0;
}

B. Hurdle Parsing

模拟

代码实现
print(*map(len, input()[1:-1].split('|')))

C. Move Segment

字符串压缩RLE

代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)

using namespace std;

int main() {
    int n, k;
    string s;
    cin >> n >> k >> s;
    
    vector<pair<char, int>> rle;
    for (char c : s) {
        if (rle.size() and rle.back().first == c) rle.back().second++;
        else rle.emplace_back(c, 1);
    }
    
    int one = 0;
    rep(i, rle.size()) {
        if (rle[i].first == '1') {
            one++;
            if (one == k) {
                swap(rle[i-1], rle[i]);
            }
        }
    }
    
    string ans;
    for (auto [c, len] : rle) {
        rep(i, len) ans += c;
    }
    
    cout << ans << '\n';
    
    return 0;
}

D. Strange Mirroring

考虑 \(\lfloor\dfrac{k}{n}\rfloor\) 的二进制表示中 1 的个数的奇偶性,如果是奇数就要修改大小写,否则不需要修改大小写

代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)

using namespace std;
using ll = long long;

char flip(char c) {
    if (islower(c)) return toupper(c);
    return tolower(c);
}

int main() {
    string s;
    cin >> s;
    int n = s.size();
    
    int q;
    cin >> q;
    rep(qi, q) {
        ll k;
        cin >> k;
        --k;
        int si = k%n;
        k /= n;
        int cnt = __builtin_parityll(k);
        char ans = s[si];
        if (cnt%2) ans = flip(ans);
        cout << ans << ' ';
    }
    
    return 0;
}

E. 1D Bucket Tool

用并查集来维护同色的块

代码实现
#include <bits/stdc++.h>
#include <atcoder/all>
using namespace atcoder;
#define rep(i, n) for (int i = 0; i < (n); ++i)

using namespace std;

int main() {
    int n, q;
    cin >> n >> q;
    
    vector<int> cnt(n+2, 1);
    dsu uf(n+2);
    vector<int> l(n+2), r(n+2), col(n+2);
    rep(i, n+2) l[i] = r[i] = col[i] = i;
    
    rep(qi, q) {
        int type;
        cin >> type;
        if (type == 1) {
            int x, c;
            cin >> x >> c;
            x = uf.leader(x);
            int sz = uf.size(x);
            
            cnt[col[x]] -= sz;
            col[x] = c;
            cnt[col[x]] += sz;
            
            {
                int li = uf.leader(l[x]-1);
                if (col[li] == c) {
                    int nl = l[li], nr = r[x];
                    uf.merge(li, x);
                    x = uf.leader(x);
                    l[x] = nl; r[x] = nr; col[x] = c;
                }
            }
            {
                int ri = uf.leader(r[x]+1);
                if (col[ri] == c) {
                    int nl = l[x], nr = r[ri];
                    uf.merge(ri, x);
                    x = uf.leader(x);
                    l[x] = nl; r[x] = nr; col[x] = c;
                }
            }
        }
        else {
            int c;
            cin >> c;
            cout << cnt[c] << '\n';
        }
    }
    
    return 0;
}

F. Exchange Game

记忆化搜索
\(f(S)\) 表示从状态 \(S\) 开始的胜负

代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)

using namespace std;
using S = tuple<vector<int>, vector<int>, vector<int>>;

int main() {
    int n, m, l;
    cin >> n >> m >> l;
    
    vector<int> a(n), b(m), c(l);
    rep(i, n) cin >> a[i];
    rep(i, m) cin >> b[i];
    rep(i, l) cin >> c[i];
    
    ranges::sort(a);
    ranges::sort(b);
    ranges::sort(c);
    
    map<S, bool> memo;
    auto f = [&](auto& f, S s) {
        if (memo.count(s)) return memo[s];
        auto [a, b, c] = s;
        bool res = false;
        rep(i, a.size()) {
            auto na = a, nc = c;
            nc.push_back(a[i]);
            na.erase(na.begin()+i);
            ranges::sort(nc);
            if (!f(f, S(b, na, nc))) res = true; 
            rep(j, nc.size()) {
                if (nc[j] < a[i]) {
                    auto na2 = na, nc2 = nc;
                    nc2.erase(nc2.begin()+j);
                    na2.push_back(nc[j]);
                    ranges::sort(na2);
                    if (!f(f, S(b, na2, nc2))) res = true; 
                }
            }
        }
        return memo[s] = res;
    };
    
    if (f(f, S(a, b, c))) puts("Takahashi");
    else puts("Aoki");
    
    return 0;
}

G. Another Shuffle Window

不难看出总方案数为 \((n-k+1) \times k!\),下面默认上下都除以 \(k!\)
考虑打乱顺序后逆序数会发生什么变化,最后只需看打乱的范围里的逆序数即可
也就是说原序列的逆序数 \(-\) 原序列区间中的逆序数 \(+\) 区间中打乱顺序后的逆序数就能得到最终的逆序数
对于第一部分和第三部分是固定的,其中区间中打乱顺序后的逆序数的期望就是 \(\dfrac{{}_kC_2}{2}\)
对于原序列区间中的逆序数,可以用一个队列维护长度为 \(k\) 的滑动窗口

代码实现
#include <bits/stdc++.h>
#include <atcoder/all>
using namespace atcoder;
#define rep(i, n) for (int i = 0; i < (n); ++i)

using namespace std;
using ll = long long;
using mint = modint998244353;

int main() {
    int n, k;
    cin >> n >> k;
    
    vector<int> p(n);
    rep(i, n) cin >> p[i], p[i]--;
    
    ll base = 0;
    {
        fenwick_tree<int> t(n);
        rep(i, n) {
            base += t.sum(p[i], n);
            t.add(p[i], 1);
        }
    }
    
    mint ans;
    {
        fenwick_tree<int> t(n);
        ll now = 0;
        queue<int> q;
        rep(i, n) {
            now += t.sum(p[i], n);
            t.add(p[i], 1);
            q.push(i);
            if (q.size() == k) {
                ans += now;
                int j = q.front(); q.pop();
                t.add(p[j], -1);
                now -= t.sum(0, p[j]);
            }
        }
    }
    ans /= (n-k+1);
    ans = mint(base) - ans + mint(k)*(k-1)/2/2;
    cout << ans.val() << '\n';
    
    return 0;
}