前言

废物只会前四题了,在手机上敲得题解大家将就看


题解


A.Wakey Wakey

任意长度区间都存在绝对众数,考虑区间长度为2时,任意相邻两项都相等,所以整个序列就只有一种数字,输出m%p即可

#include<bits/stdc++.h>
using i64 = long long;
using u64 = unsigned long long;
void solve() {
    int n, m, p;
    std::cin >> n >> m >> p;
    std::cout << m % p << '\n';
} 
signed main() {
    std::ios::sync_with_stdio(0);
    std::cout.tie(0);
    std::cin.tie(0);
    i64 t = 1; 
    std::cin >> t;
    while (t--) {
        solve();
    }
}

B.Substring Not Subsequence

题意为,有多少种字符串仅作为子串出现且不作为不连续的子序列出现,那我们考虑abb,ab就不是一个合法的目标串,因为下标1,2为子串ab,下标1,3为不连续的子序列ab,再考虑aab,下标2,3为子串ab,下标1,3为不连续的子序列ab,所以ab也不是合法序列,你可以多举几个例子发现,如果要满足目标串,我们枚举子串的左端点,如果当前枚举的左端点是第一次出现的字符,那就找后面有多少种字符只出现过一次,这就是答案

#include<bits/stdc++.h>
using i64 = long long;
using u64 = unsigned long long;
void solve() {
    int n;
    std::cin >> n;
    std::string s;
    std::cin >> s;
    s = ' ' + s;
    std::vector<int> suf(n + 2);
    std::map<char, int> mp;
    int cnt = 0;
    for (int i = n; i >= 1; i--) {
        if (!mp[s[i]]) {
            suf[i] = suf[i + 1] + 1;
            cnt++;
            mp[s[i]] = 1;
        }
        else {
            suf[i] = suf[i + 1];
        }
    }
    mp.clear();
    int ans = 0;
    for (int i = 1; i <= n; i++) {
        if (!mp[s[i]]) {
            ans += suf[i + 1];
            mp[s[i]] = 1;
        }
    }
    std::cout << ans + cnt << '\n';
} 
signed main() {
    std::ios::sync_with_stdio(0);
    std::cout.tie(0);
    std::cin.tie(0);
    i64 t = 1; 
    // std::cin >> t;
    while (t--) {
        solve();
    }
}

C.序列

0011为一对,而且每一对00一定会对应固定的11,是不是就很像括号匹配了,我们再考虑如果一对0011可以直接删除,那他跟其他括号的删除就没有先后关系,我们来看最后一个样例,下标1和6对应的00是一对,这一对0011只能在下标2和下标3的00和下标为7和8的00删除之后才能删除,那我们把删除每个0011看成一个事件,最后一个样例即有ABCDE五个事件,其中下标1和6对应的00删除的事件我们认为他是事件C,五个事件没有约束发生的情况一共有A(5,5)种,但C事件必须在AB事件都发生之后才能发生,那去重一下就是A(5,5)/3=40种,所以我们就计算每一对0011会至少在多少对0011删除之后删除,用A(n,n)/(我们算出来每对0011至少在多少对0011删除之后才能删除的数值的乘积)就是答案,我们要维护每一对0011删除之前至少要删除多少对就可以给每一对0011打一个时间戳,我是按照入栈时间把每一对0011打上时间戳,然后用mex去维护的这东西,大家看看代码,不明白的再问我吧

#include<bits/stdc++.h>

using i64 = long long;
using u64 = unsigned long long;

const i64 mod = 1e9 + 7;

i64 ksm(i64 a, i64 b) {
    i64 res = 1;
    while(b) {
        if (b & 1) res = res * a % mod;
        a = a * a % mod;
        b >>= 1;
    }

    return res;
}

void solve() {
    i64 n;
    std::cin >> n;
    std::string s;
    std::cin >> s;
    s = ' ' + s;

    std::stack<i64> st;
    std::vector<i64> cnt(n * 4 + 1);
    i64 cnt0 = 0, cnt1 = 0, num = 0;
    bool flag = 0;
    for (i64 i = 1; i <= 4 * n; i++) {
        st.push(i);
        if (s[i] == '0') {
            cnt0++;
        }
        else {
            cnt1++;
            if (cnt1 + cnt0 >= 4) {
                std::vector<i64> v;
                for (i64 j = 1; j <= 4; j++) {
                    v.push_back(st.top());
                    st.pop();
                }

                if (s[v[0]] == '1' && s[v[1]] == '1' && s[v[2]] == '0' && s[v[3]] == '0') {
                    cnt1 -= 2;
                    cnt0 -= 2;
                    num++;
                    cnt[v[0]] = num;
                    cnt[v[1]] = num;
                    cnt[v[2]] = num;
                    cnt[v[3]] = num;
                }
                else {
                    for (i64 j = 3; j >= 0; j--) {
                        st.push(v[j]);
                    }
                }
            }
        }
    }
    if (st.size()) {
        std::cout << 0 << '\n';
        return;
    }
    i64 res = 1;
    std::vector<i64> mp(n + 1);
    std::set<i64> stt;
    for (i64 i = 1; i <= n; i++) {
        stt.insert(i);
    }
    for (i64 i = 1; i <= 4 * n; i++) {
        if (!mp[cnt[i]]) {
            i64 q = *stt.begin();
            res = res * (cnt[i] - q + 1) % mod;
            stt.erase(cnt[i]);
            mp[cnt[i]] = 1;
        }
    }

    i64 ans = 1;
    for (i64 i = 1; i <= n; i++) {
        ans = ans * i % mod;
    }
    // std::cout << ans << ' ' << res << '\n';
    std::cout << ans * ksm(res, mod - 2) % mod << '\n';
} 

signed main() {
    std::ios::sync_with_stdio(0);
    std::cout.tie(0);
    std::cin.tie(0);

    i64 t = 1; 
    std::cin >> t;
    while (t--) {
        solve();
    }
}

D.数据结构

跟出题人哥哥学的解法,求出初始的sum和,线段树维护每个区间奇偶数的数量,update的时候每次直接推到一个区间只有奇数或只有偶数的区间,具体细节看代码吧,我觉得出题人哥哥写的还是比较明确的

#include <bits/stdc++.h>
#define lowbit(x) x & (-x)

using i64 = long long;
using u64 = unsigned long long;

#define lson (rt << 1)
#define rson (rt << 1 | 1)

int a[500005];
const int mod = 998244353;
i64 ans = 0;

struct treenode {//1是奇,2是偶
    int cnt1, cnt2;
    int mx, mn;
    int lz;
};


struct Segment_Tree {
    std::vector<treenode> tr;

    void init (int n) {
        tr.resize((n + 1) << 2);
        build(1, 1, n);
    }

    void merge (int rt) {
       tr[rt].mn = std::min(tr[lson].mn, tr[rson].mn);
       tr[rt].mx = std::max(tr[lson].mx, tr[rson].mx);
       tr[rt].cnt1 = tr[lson].cnt1 + tr[rson].cnt1;
       tr[rt].cnt2 = tr[lson].cnt2 + tr[rson].cnt2;
    }

    void push_down(int rt) {
        if (tr[rt].lz) {
            update(lson, tr[rt].lz);
            update(rson, tr[rt].lz);
            tr[rt].lz = 0;
        }
    }

    void build(int rt, int l, int r) {
        if (l == r) {
            tr[rt].mn = tr[rt].mx = a[l];
            if (a[l] & 1) {
                tr[rt].cnt1 = 1;
            }
            else {
                tr[rt].cnt2 = 1;
            }
            return;
        }

        int mid = l + r >> 1;
        build(lson, l, mid);
        build(rson, mid + 1, r);
        merge(rt);
    }

    void update(int rt, int x) {
        tr[rt].mn += x;
        tr[rt].mx += x;
        if (x & 1) {
            std::swap(tr[rt].cnt1, tr[rt].cnt2);
        }
        tr[rt].lz += x;
    }

    void query1(int rt, int l, int r, int L, int R) {
        if (!tr[rt].cnt1 || (L > tr[rt].mx || R < tr[rt].mn)) {
            return;
        }
        if (L <= tr[rt].mn && R >= tr[rt].mx && !tr[rt].cnt2) {
            ans -= tr[rt].cnt1;
            update(rt, -1);
            return;
        }
        
        push_down(rt);
        
        int mid = l + r >> 1;
        query1(lson, l, mid, L, R);
        query1(rson, mid + 1, r, L, R);
        merge(rt);
    }

    void query2(int rt, int l, int r, int L, int R) {
        if (!tr[rt].cnt2 || (L > tr[rt].mx || R < tr[rt].mn)) {
            return;
        }
        if (L <= tr[rt].mn && R >= tr[rt].mx && !tr[rt].cnt1) {
            ans -= tr[rt].cnt2;
            update(rt, -1);
            return;
        }
        
        push_down(rt);
        
        int mid = l + r >> 1;
        query2(lson, l, mid, L, R);
        query2(rson, mid + 1, r, L, R);
        merge(rt);
    }
}tr;

void solve() {
    int n, q;
    std::cin >> n >> q;
    
    for (int i = 1; i <= n; i++) {
        std::cin >> a[i];
        ans += a[i];
    }

    std::sort(a + 1, a + 1 + n);

    tr.init(n);

    i64 res = 0;
    for (int i = 1; i <= q; i++) {
        int l, r, c;
        std::cin >> l >> r >> c;
        if (c == 0) {
            tr.query2(1, 1, n, l, r);
        }
        else {
            tr.query1(1, 1, n, l, r);
        }

        res ^= i * ans;
    }

    std::cout << res << '\n';
} 

signed main() {
    std::ios::sync_with_stdio(0);
    std::cout.tie(0);
    std::cin.tie(0);

    i64 t = 1; 
    // std::cin >> t;
    while (t--) {
        solve();
    }
}