Codeforces Round 915 (Div. 2)

Codeforces Round 915 (Div. 2)

唉,菜狗。

A - Cover in Water

int main() {
    IOS;
    for (cin >> _; _; --_) {
        cin >> n >> m;
        cout << max(n, m) << '\n';
    }
    return 0;
}

B - Begginer's Zelda

除了最后一次操作,每次操作会稳定减少两个叶子节点。

const int N = 1e5 + 5, M = N << 1;
 
int n, m, _, k, cas;
int h[N], to[M], ne[M], tot;
 
void init(int n) {
    tot = 0;
    memset(h, 0, sizeof(int) * (n + 1));
}
 
void add(int u, int v) {
    ne[++tot] = h[u];
    to[h[u] = tot] = v;
}
 
int dfs(int x, int f) {
    int ans = 0, c = 0;
    for (int i = h[x], y = to[i]; i; y = to[i = ne[i]]) if (y ^ f) {
        ans += dfs(y, x);
        ++c;
    }
    return x == 1 && c < 2 ? ans + 1 : max(ans, 1);
}
 
int main() {
    IOS;
    for (cin >> _; _; --_) {
        cin >> n;
        init(n);
        rep (i, 2, n) {
            int x, y; cin >> x >> y;
            add(x, y); add(y, x);
        }
        cout << (dfs(1, 0) + 1 >> 1) << '\n';
    }
    return 0;
}

C - Largest Subsequence

烦,一开始读成字串了,写了半天,发现样例都过不去。

int main() {
    IOS;
    for (cin >> _; _; --_) {
        cin >> n >> s + 1;
        VI a;
        rep (i, 1, n) {
            while (!a.empty() && s[a.back()] < s[i]) a.pop_back();
            a.pb(i);
        }
        int len = 0;
        for (int i = 0; i < a.size() && s[a[i]] == s[a[0]]; ++i, ++len);
        for (int i = 0, j = a.size() - 1; i < j; ++i, --j) swap(s[a[i]], s[a[j]]);
        bool f = 1;
        rep (i, 2, n) if (s[i] < s[i - 1]) f = 0;
        cout << (f ? int(a.size()) - len : -1) << '\n';
    }
    return 0;
}

D - Cyclic MEX

这题考察的是 mex。

考虑对于一个排列,如何区间 (l, r) 求 mex 呢?

考虑到 mex 性质,显然是 \(min(min(a_1 ... a_{l - 1}), min(a_{r + 1} ... a_n))\) (下标从 1 开始)

这道题是循环排列,即把第一个数不断的放到最后或把一个数从最后一个不断放到最前面,即只需考虑前缀最小值或后缀最小值。

考虑一般都是 1 到 n,所以这里选择维护前缀最小值,维护前缀最小值,经典的就是单调栈。

把一个数从队首移到队末,对于维护前缀最小值来说,就是把不断弹栈并把贡献不断减去,再加上移动后的贡献即可。

单调栈首先塞个 -1 以防栈空,对于序列最后一个数,mex 一定是 n, 由于最后一个数之后不会在加入,会导致最后一个数位置的 mex 没有计算,所以记得加 n.

这题要拆环,取数是要取模,为了方便,下表从 0 开始

int main() {
    IOS;
    for (cin >> _; _; --_) {
        cin >> n;
        rep (i, 0, n - 1) cin >> a[i];
        stack<int> st; st.emplace(-1);
        ll res = n, ans = 0;
        rep (i, 0, n * 2 - 1) {
            while (st.size() > 1 && a[i % n] < a[st.top() % n]) {
                int x = st.top(); st.pop();
                res -= 1ll * a[x % n] * (x - st.top());
            }
            res += 1ll * a[i % n] * (i - st.top());
            st.emplace(i);
            if (i >= n) umax(ans, res);
        }
        cout << ans << '\n';
    }
    return 0;
}
posted @ 2023-12-17 09:33  洛绫璃  阅读(133)  评论(0编辑  收藏  举报