A. 11/22 String

模拟

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

using namespace std;

bool solve() {
    int n;
    string s;
    cin >> n >> s;
    
    if (n%2 == 0) return false;
    
    int one = n/2;
    string t;
    t += string(one, '1');
    t += '/';
    t += string(one, '2');
    return s == t;
}

int main() {
    if (solve()) puts("Yes");
    else puts("No");
    
    return 0;
}

B. 1122 String

模拟

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

using namespace std;

bool solve() {
    string s;
    cin >> s;
    int n = s.size();
    
    if (n&1) return false;
    
    rep(i, n/2) {
        if (s[i*2] != s[i*2+1]) return false;
    }
    set<char> st;
    rep(i, n/2) st.insert(s[i*2]);
    return st.size() == n/2;
}

int main() {
    if (solve()) puts("Yes");
    else puts("No");
    
    return 0;
}

C. 11/22 Substring

先对字符串RLE一遍,然后遍历每个 /,然后取左边连续的 1 的个数和右边连续的 2 的个数的最小值,再将它 \(\times 2 + 1\) 就可以作为一个备选答案
也可以遍历每个 /,然后从这个位置开始向两边进行扩展

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

using namespace std;

int main() {
    int n;
    string s;
    cin >> n >> s;
    
    s = '$'+s+'$';
    n = s.size();
    
    int ans = 1;
    rep(i, n) if (s[i] == '/') {
        int x = 1;
        while (s[i-x] == '1' and s[i+x] == '2') x++;
        int now = x*2-1;
        ans = max(ans, now);
    }
    
    cout << ans << '\n';
    
    return 0;
}

D. 1122 Substring

双指针,开一个桶来维护窗口中每种数的出现次数
注意需要分别对奇偶性下标进行讨论

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

using namespace std;

int main() {
    int n;
    cin >> n;
    
    vector<int> a(n);
    rep(i, n) cin >> a[i];
    
    int ans = 0;
    rep(si, 2) {
        vector<int> cnt(n+1);
        int r = si;
        for (int l = si; l+1 < n; l += 2) {
            while (r+1 < n) {
                if (a[r] != a[r+1]) break;
                if (cnt[a[r]]) break;
                cnt[a[r]]++;
                r += 2;
            }
            ans = max(ans, r-l);
            if (l == r) r += 2;
            else cnt[a[l]]--;
        }
    }
    
    cout << ans << '\n';
    
    return 0;
}

E. 11/22 Subsequence

可以考虑二分 \(1\)\(2\) 的长度
那么问题就变成了能否取出 11...1/22...2 这样的子序列
可以用vector来维护每种字符的位置,然后二分找到下一个需要的位置即可

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

using namespace std;

int main() {
    int n, q;
    string s;
    cin >> n >> q >> s;
    
    vector<vector<int>> is(3);
    rep(i, n) {
        int c = s[i]-'0';
        if (s[i] == '/') c = 0;
        is[c].push_back(i);
    }
    
    const int INF = 1001001001;
    auto getNext = [&](int c, int i, int x) {
        if (x == 0) return i;
        auto& nis = is[c];
        int j = lower_bound(nis.begin(), nis.end(), i) - nis.begin();
        j += x-1;
        if (j < nis.size()) return nis[j]+1;
        return INF;
    };
    
    rep(qi, q) {
        int l, r;
        cin >> l >> r;
        --l;
        
        auto judge = [&](int k) {
            int i = l;
            i = getNext(1, i, k);
            i = getNext(0, i, 1);
            i = getNext(2, i, k);
            return i <= r;
        };
        
        int ac = -1, wa = n;
        while (ac+1 < wa) {
            int wj = (ac+wa)/2;
            (judge(wj) ? ac : wa) = wj;
        }
        int ans = 0;
        if (ac == -1) ans = 0;
        else ans = ac*2+1;
        cout << ans << '\n';
    }
    
    return 0;
}

F. 1122 Subsequence

状压dp
dp[S] 表示到目前为止已经使用过的数的集合为 \(S\) 时贪心地取时下一个位置的最小值

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

using namespace std;

inline void chmin(int& a, int b) { if (a > b) a = b; }

int main() {
    int n;
    cin >> n;
    
    vector<int> a(n);
    rep(i, n) cin >> a[i], a[i]--;
    
    int m = 20, m2 = 1<<m;
    vector<vector<int>> is(m);
    rep(i, n) is[a[i]].push_back(i);
    
    const int INF = 1001001001;
    auto getNext = [&](int c, int i, int x) {
        if (x == 0) return i;
        auto& nis = is[c];
        int j = lower_bound(nis.begin(), nis.end(), i) - nis.begin();
        j += x-1;
        if (j < nis.size()) return nis[j]+1;
        return INF;
    };
    
    vector<int> dp(m2, INF);
    dp[0] = 0;
    
    int ans = 0;
    rep(s, m2) {
        if (dp[s] != INF) ans = max(ans, popcount(1u*s)); 
        rep(c, m) {
            if (s>>c&1) continue;
            chmin(dp[s|1<<c], getNext(c, dp[s], 2));
        }
    }
    ans *= 2;
    
    cout << ans << '\n';
    
    return 0;
}

G. Fibonacci Product

数学题