前言

emmm,我着急吃饭赶了一篇题解,如果哪写的有问题欢迎大家指出,代码应该都是没问题的,如果有问题可以给我发私信或者评论,b站牛客竞赛应该也会有视频讲解)


题解


A.tb的区间问题

枚举所有长度为k的区间的和取max就好了,滑动窗口的写法

#include<bits/stdc++.h>

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

void solve() {
    int n, k;
    std::cin >> n >> k;

    std::vector<int> a(n + 1);
    for (int i = 1; i <= n; i++) {
        std::cin >> a[i];
    }

    i64 ans = -1, sum = 0;
    for (int i = 1; i <= n; i++) {
        sum += a[i];
        if (i >= n - k) {
            sum -= a[i - (n - k)];
            ans = std::max(ans, sum);
        }
        // std::cout << sum << '\n';
    }

    std::cout << ans << '\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.tb的字符串问题

在我看来就是括号匹配问题,有两种括号罢了,大家不会的可以先去网上学习一下括号匹配的写法,用栈来维护

#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::stack<char> st;
    for (int i = 1; i <= n; i++) {
        st.push(s[i]);
        if (st.size() > 1) {
            char q1 = st.top();
            st.pop();
            char q2 = st.top();
            st.pop();
            if ((q1 == 'c' && q2 == 'f') || (q1 == 'b' && q2 == 't')) {
                continue;
            }
            st.push(q2);
            st.push(q1);
        }
    }

    std::cout << st.size() << '\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.tb的路径问题

这个规律很好找的,大家可以手玩样例或者打表观察一下,肯定是要根据2来跳的

#include<bits/stdc++.h>

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

void solve() {
    int n;
    std::cin >> n;
    if (n == 1) {
        std::cout << 0;
        return;
    }
    if (n == 2) {
        std::cout << 2;
        return;
    }
    if (n == 3) {
        std::cout << 4;
        return;
    }
    if (n & 1) {
        std::cout << 6;
    }
    else {
        std::cout << 4;
    }
    
}  

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.tb的平方问题

范围内的完全平方数一共也没多少嘛,那我们直接枚举所有的就好了,其余部分我们考虑一个板子题,有长度为n的数组,问你区间和为k的有多少,这题更简单,没有负数,那对于每一个确定的区间右端点来说,每一个完全平方数对应的肯定只有一个区间左端点,最后用一个差分数组来维护就好了。

#include<bits/stdc++.h>

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

void solve() {
    int n, q;
    std::cin >> n >> q;

    std::vector<int> a(n + 1), c(n + 2);
    std::map<int, int> mp;
    mp[0] = 0;
    int sum = 0;
    
    for (int i = 1; i <= n; i++) {
        std::cin >> a[i];
        sum += a[i];
        for (int j = 1; j * j <= sum; j++){
            if (mp.count(sum - j * j)) {
                c[mp[sum - j * j] + 1]++;
                c[i + 1]--;
            }
        }
        mp[sum] = i;
    }

    for (int i = 1; i <= n; i++) {
        c[i] += c[i - 1];
        // std::cout << c[i] << ' ';
    }
    // std::cout << '\n';

    while (q--) {
        int x;
        std::cin >> x;
        std::cout << c[x] << '\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();
    }
}

E.tb的数数问题

这个题的话就去找每个没有出现的数,他的倍数都是false的,其余的都是true,调和级数log的复杂度。

#include<bits/stdc++.h>

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

void solve() {
    int n;
    std::cin >> n;

    std::vector<int> vis(1000005, 0), flag(1000005, 0), a(n + 1);
    bool f = 0;
    int mx = -1;
    for (int i = 1; i <= n; i++) {
        std::cin >> a[i];
        if (a[i] == 1) {
            f = 1;
        }
        mx = std::max(mx, a[i]);
        vis[a[i]] = 1;
    }

    if (!f) {
        std::cout << 0;
        return;
    }

    for (int i = 2; i <= mx; i++) {
        if (!vis[i] && !flag[i]) {
            for (int j = i * 2; j <= mx; j += i) {
                vis[j] = 0;
                flag[j] = 1; 
            }
        }
    }

    int ans = 0;
    for (int i = 1; i <= mx; i++) {
        if (vis[i]) {
            ans++;
        }
    }

    std::cout << ans << '\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();
    }
}

F.tb的排列问题

这个感觉我写的可能有点麻烦了,我的想法是按b的顺序看a中没出现的数字可以出现在哪几个位置,然后默认给他填到当前位置往后最近的没有填过的-1的位置,把这些乘起来,实现起来我用了个树状数组

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

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

struct Fenwick {
    int n;
    std::vector<int> tr;
    std::stack<std::pair<int,int>> sta;
    void reset(int m) {
        n = m;
        tr.clear();
        tr.resize(n + 1);
        clear();
    }
    void modify(int u, int x) {
        sta.push(std::make_pair(u, x));
        for (int i = u + 1; i <= n; i += lowbit(i))
            tr[i] += x;
    }
    int query(int u) {
        int x = 0;
        for (int i = u + 1; i >= 1; i -= lowbit(i))
            x += tr[i];
        return x;
    }
    int query(int l, int r) { // [l, r]
        return query(r) - query(l - 1);
    }
    void pop() {
        while(!sta.empty()) {
			auto cur = sta.top();
			int x = cur.first, v = cur.second;
			for (int i = x + 1 ;i <= n; i += lowbit(i))
				tr[i] -= v;
			sta.pop();
            break;
		}
    }
    void clear() {
        while(!sta.empty()) {
			auto cur = sta.top();
			int x = cur.first, v = cur.second;
			for (int i = x + 1 ;i <= n; i += lowbit(i))
				tr[i] -= v;
			sta.pop();
		}
    }
}tr;

template<class T>
constexpr T power(T a, i64 b) {
    T res = 1;
    for (; b; b /= 2, a *= a) {
        if (b % 2) {
            res *= a;
        }
    }
    return res;
}

constexpr i64 mul(i64 a, i64 b, i64 p) {
    i64 res = a * b - i64(1.L * a * b / p) * p;
    res %= p;
    if (res < 0) {
        res += p;
    }
    return res;
}

template<int P>
struct MInt {
    int x;
    constexpr MInt() : x{} {}
    constexpr MInt(i64 x) : x{norm(x % getMod())} {}
    
    static int Mod;
    constexpr static int getMod() {
        if (P > 0) {
            return P;
        } else {
            return Mod;
        }
    }
    constexpr static void setMod(int Mod_) {
        Mod = Mod_;
    }
    constexpr int norm(int x) const {
        if (x < 0) {
            x += getMod();
        }
        if (x >= getMod()) {
            x -= getMod();
        }
        return x;
    }
    constexpr int val() const {
        return x;
    }
    explicit constexpr operator int() const {
        return x;
    }
    constexpr MInt operator-() const {
        MInt res;
        res.x = norm(getMod() - x);
        return res;
    }
    constexpr MInt inv() const {
        assert(x != 0);
        return power(*this, getMod() - 2);
    }
    constexpr MInt &operator*=(MInt rhs) & {
        x = 1LL * x * rhs.x % getMod();
        return *this;
    }
    constexpr MInt &operator+=(MInt rhs) & {
        x = norm(x + rhs.x);
        return *this;
    }
    constexpr MInt &operator-=(MInt rhs) & {
        x = norm(x - rhs.x);
        return *this;
    }
    constexpr MInt &operator/=(MInt rhs) & {
        return *this *= rhs.inv();
    }
    friend constexpr MInt operator*(MInt lhs, MInt rhs) {
        MInt res = lhs;
        res *= rhs;
        return res;
    }
    friend constexpr MInt operator+(MInt lhs, MInt rhs) {
        MInt res = lhs;
        res += rhs;
        return res;
    }
    friend constexpr MInt operator-(MInt lhs, MInt rhs) {
        MInt res = lhs;
        res -= rhs;
        return res;
    }
    friend constexpr MInt operator/(MInt lhs, MInt rhs) {
        MInt res = lhs;
        res /= rhs;
        return res;
    }
    friend constexpr std::istream &operator>>(std::istream &is, MInt &a) {
        i64 v;
        is >> v;
        a = MInt(v);
        return is;
    }
    friend constexpr std::ostream &operator<<(std::ostream &os, const MInt &a) {
        return os << a.val();
    }
    friend constexpr bool operator==(MInt lhs, MInt rhs) {
        return lhs.val() == rhs.val();
    }
    friend constexpr bool operator!=(MInt lhs, MInt rhs) {
        return lhs.val() != rhs.val();
    }
};

template<>
int MInt<0>::Mod = 998244353;

template<int V, int P>
constexpr MInt<P> CInv = MInt<P>(V).inv();

constexpr int P = 998244353;
using Z = MInt<P>;

void solve() {
    int n, w;
    std::cin >> n >> w;

    tr.reset(n + 1);
    std::vector<int> a(n + 1), vis(n + 1, 0);
    for (int i = 1; i <= n; i++) {
        std::cin >> a[i];
    }

    for (int i = n; i >= 1; i--) {
        if (a[i] == -1) {
            tr.modify(i, 1);
        }
        else {
            vis[a[i]] = i;
        }
    }

    std::vector<int> b(n + 1);
    for (int i = 1; i <= n; i++) {
        std::cin >> b[i];
    }

    bool flag = 1;

    Z ans = 1;
    for (int i = 1; i <= n; i++) {
        if (!vis[b[i]]) {
            int num = tr.query(1, std::min(n, i + w));
            if (num) {
                ans *= num;
                tr.pop();
            }
            else {
                tr.pop();
                flag = 0;
//                 std::cout << 0 << '\n';
//                 return;
            }
        }
        else {
            if (vis[b[i]] > i + w) {
                flag = 0;
            }
        }
    } 

    if (!flag) {
        std::cout << 0 << '\n';
    }
    else {
        std::cout << ans << '\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();
    }
}