T1. 美克斯

排列的性质非常优秀,考虑利用排列的性质快速求解。

注意到 \(\operatorname{mex}(S)\)\(S\) 内没有出现的最小的自然数,又因为这是一个 \(0 \sim n-1\) 的排列,那么 \(\{a_l, a_{l+1}, \cdots, a_r\}\) 中未出现的自然数可以理解为 \(a_1, a_2, \cdots, \cdots, a_{l-1}\),以及 \(a_{r+1}, \cdots, a_{n-1}, a_n\),函数值也就是这些未出现的自然数中的最小值。

所以维护前后缀的最小值就能 \(O(N)\) 回答询问。

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

using namespace std;

int main() {
    int n, q;
    cin >> n >> q;
    
    vector<int> a(n);
    rep(i, n) cin >> a[i];
    
    vector<int> pref(n+1, n), suff(n+1, n);
    rep(i, n) pref[i+1] = min(pref[i], a[i]);
    for (int i = n-1; i >= 0; --i) suff[i] = min(suff[i+1], a[i]);
    
    rep(qi, q) {
        int l, r;
        cin >> l >> r;
        --l;
        int ans = min(pref[l], suff[r]);
        cout << ans << '\n';
    }
    
    return 0;
}

T2. 二进制

可以直接数位dp,或者考虑组合数学的做法

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

using namespace std;
using ll = long long;

const int M = 60;
ll dp[61][2][2][61];

void solve() {
    ll n; int k;
    cin >> n >> k;
    n++;
    
    rep(i, M+1)rep(j, 2)rep(s, 2)rep(p, k+1) dp[i][j][s][p] = 0;
    dp[M][0][0][0] = 1;
    for (int i = M-1; i >= 0; --i) {
        rep(j, 2)rep(s, 2)rep(p, k+1) {
            ll now = dp[i+1][j][s][p];
            if (now == 0) continue;
            rep(a, 2) {
                int ns = s, np = p+a;
                if (s == 0) {
                    if (a < (n>>i&1)) ns = 1;
                    if (a > (n>>i&1)) continue;
                }
                if (np > k) continue;
                dp[i][j][ns][np] += now;
                if (j == 0 and a) dp[i][1][ns][np] += now; 
            }
        }
    }
    
    ll ans = dp[0][1][1][k]/k;
    cout << ans << '\n';
}

int main() {
    int t = 1;
    
    while (t--) solve();
    
    return 0;
}

T3. 斯瓦普

首先对于所有满足 \(a_i > b_i\)\(i\),交换 \(a_i\)\(b_i\)
考虑创建一个新序列 \(\{(a_1, b_1), (a_2, b_2), \cdots, (a_n, b_n)\}\) 并将其做升序排序,记做序列 \(c\)
然后用 std::set 来维护序列 \(a\),答案初始值就是 \(a\) 的极差
依次尝试将每个 \(a_i\) 替换成 \(b_i\) 后检验会不会令答案变小

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

using namespace std;
using P = pair<int, int>;

int main() {
    int n;
    cin >> n;
    
    vector<int> a(n), b(n);
    rep(i, n) cin >> a[i];
    rep(i, n) cin >> b[i];
    
    rep(i, n) {
        if (a[i] > b[i]) swap(a[i], b[i]);
    }
    
    multiset<int> st;
    rep(i, n) st.insert(a[i]);
    
    int ans = *st.rbegin() - *st.begin();
    vector<P> c(n);
    rep(i, n) c[i] = P(a[i], b[i]);
    
    sort(c.begin(), c.end());
    
    rep(i, n) {
        st.erase(st.find(c[i].first));
        st.insert(c[i].second);
        ans = min(ans, *st.rbegin() - *st.begin());
    }
    
    cout << ans << '\n';
    
    return 0;
}

T4. 超级车流量

原题:CF1747E

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

using namespace std;
using ll = long long;

//const int mod = 998244353;
const int mod = 1000000007;
struct mint {
    ll x;
    mint(ll x=0):x((x%mod+mod)%mod) {}
    mint operator-() const {
        return mint(-x);
    }
    mint& operator+=(const mint a) {
        if ((x += a.x) >= mod) x -= mod;
        return *this;
    }
    mint& operator-=(const mint a) {
        if ((x += mod-a.x) >= mod) x -= mod;
        return *this;
    }
    mint& operator*=(const mint a) {
        (x *= a.x) %= mod;
        return *this;
    }
    mint operator+(const mint a) const {
        return mint(*this) += a;
    }
    mint operator-(const mint a) const {
        return mint(*this) -= a;
    }
    mint operator*(const mint a) const {
        return mint(*this) *= a;
    }
    mint pow(ll t) const {
        if (!t) return 1;
        mint a = pow(t>>1);
        a *= a;
        if (t&1) a *= *this;
        return a;
    }

    // for prime mod
    mint inv() const {
        return pow(mod-2);
    }
    mint& operator/=(const mint a) {
        return *this *= a.inv();
    }
    mint operator/(const mint a) const {
        return mint(*this) /= a;
    }
};
istream& operator>>(istream& is, mint& a) {
    return is >> a.x;
}
ostream& operator<<(ostream& os, const mint& a) {
    return os << a.x;
}

struct modinv {
  int n; vector<mint> d;
  modinv(): n(2), d({0,1}) {}
  mint operator()(int i) {
    while (n <= i) d.push_back(-d[mod%n]*(mod/n)), ++n;
    return d[i];
  }
  mint operator[](int i) const { return d[i];}
} invs;
struct modfact {
  int n; vector<mint> d;
  modfact(): n(2), d({1,1}) {}
  mint operator()(int i) {
    while (n <= i) d.push_back(d.back()*n), ++n;
    return d[i];
  }
  mint operator[](int i) const { return d[i];}
} facts;
struct modfactinv {
  int n; vector<mint> d;
  modfactinv(): n(2), d({1,1}) {}
  mint operator()(int i) {
    while (n <= i) d.push_back(d.back()*invs(n)), ++n;
    return d[i];
  }
  mint operator[](int i) const { return d[i];}
} ifacts;
mint comb(int n, int k) {
  if (n < k || k < 0) return 0;
  return facts(n)*ifacts(k)*ifacts(n-k);
}

int main() {
    int n, m;
    cin >> n >> m;
    
    if (m > n) swap(m, n);
    
    mint inv2 = mint(2).inv();
    auto d = [&](int x) {
        return mint(x+1)*inv2;
    };
    
    mint ans;
    mint pw = mint(2).pow(n+m);
    rep(i, m+1) {
        pw *= inv2;
        ans += comb(n, i)*comb(m, i)*pw*(d(n+m-i)+i+1);
    }
    
    cout << ans << '\n';
    
    return 0;
}