Codeforces Round #826 (Div. 3) A - E

A

照着题意$if \ else $即可。

void solve() {
    string s1, s2; cin >> s1 >> s2;
    int n = sz(s1), m = sz(s2);
    if (s1 == s2) cout << '=' << endl;
    else {
        if (s1[n - 1] > s2[m - 1]) cout << '<' << endl;
        else if (s2[m - 1] > s1[n - 1]) cout << '>' << endl;
        else if (s1[n - 1] == 'S'){
            if (n > m) cout << "<" <<endl;
            else if (n < m) cout << ">" << endl;
            else cout << "=\n";
        }
        else if (s1[n - 1] == 'L'){
            if (n > m) cout << ">" <<endl;
            else if (n < m) cout << "<" << endl;
            else cout << "=\n";
        }
    }
}

B

\(n=3\)之外,可以把数组分为长度大于\(n/2\)和小于\(n/2\)的前后两段,调换顺序输出。

void solve() {
    int n; cin >> n;
    if (n == 3) cout << -1 << endl;
    else {
        int mid = n / 2 + 1;
        for (int i = mid;i <= n;i++) cout << i << ' ';
        for (int i = 1;i < mid;i++) cout << i << ' ';
        cout << endl;
    }
}

C

可以枚举第一段的和为多少,然后双指针做后面的分段,时间复杂度\(O(n^2)\),赛时写了个先枚举最大段长度,再枚举第一段长度的,好像是个\(O(n^3)\),但跑得很快过了。

void solve() {
    int n; cin >> n;
    vector<int> a(n + 1), sum(n + 1);
    for (int i = 1;i <= n;i++) {
        cin >> a[i];
        sum[i] = sum[i - 1] + a[i];
    }

    for (int len = 1;len <= n;len ++) {
        bool ok = false;
        
        for (int i = 1;i <= len;i++) {
            int res = sum[i];
            for (int l = i + 1, r = i + 1;l <= n;l ++) {
                while (sum[r] - sum[l - 1] < res && r - l + 1 <= len) r ++;
                if (sum[r] - sum[l - 1] != res || r - l + 1 > len) break;
                else {
                    l = r;
                    r = r + 1;
                    if (l == n) ok = true;
                } 
            }
            if (ok) break;
        }
        if (ok) {
            cout << len << endl;
            return ;
        }
    }
    cout << n << endl;
}

D

根据完全二叉树最后一层有\(n\)个节点,则总共的节点数量为\(n*2-1\)个,建出完全二叉树。(虚空建图了,其实根本不需要写建树过程)
接下来从叶子结点向上遍历,记录左右子树的最大值和最小值,如果左子树的最大值大于右子树的最大值,则需要一次交换,且需要满足\(minval_{左子树}=maxval_{右子树}+1\)

也可以用线段树做,这里完全二叉树也可以看做是一颗线段树,做的过程就是用左右子树的信息更新父亲结点的信息,和线段树\(build\)类似。

#include <bits/stdc++.h>
#define endl '\n'
using namespace std;

void solve() {
    int n, m; cin >> n; m = n * 2 - 1;
    vector<int> a(n + 1);
    for (int i = 1;i <= n;i++) cin >> a[i];
    if (n == 1) {
        cout << 0 << endl;
        return;
    }
    bool ok = true;
    vector<int> g[m + 1], mx(m + 1), mi(m + 1), ans(m + 1);
    for (int i = m;i > 1;i--) {
        int p = i / 2;
        g[p].push_back(i);
    } //发现后面没有用到
    function<void(int x)> dfs = [&](int x) {
        int l = x * 2, r = x * 2 + 1;
        if (r <= m) {
            dfs(l); dfs(r);
            ans[x] = ans[l] + ans[r];     
            mx[x] = max(mx[l], mx[r]);
            mi[x] = min(mi[l], mi[r]);   
            if (mx[l] > mx[r] && mx[r] + 1 != mi[l]) ok = false;   
            if (mi[r] < mi[l] && mx[r] + 1 != mi[l]) ok = false;   
            if (mx[l] < mx[r] && mx[l] + 1 != mi[r]) ok = false;
            if (mi[l] == mx[r] + 1) ans[x] ++;
        }
        else mx[x] = mi[x] = a[x - n + 1];
    };
    dfs(1);
    if (!ok) cout << "-1\n";
    else cout << ans[1] << endl;
}
signed main(void) {
    cin.tie(nullptr), cout.tie(nullptr) -> ios::sync_with_stdio(false);
    int t = 1; 
    cin >> t;
    while (t --) solve(); 
    return 0;
}

E

不够分奴,想过是\(dp\),但是没仔细想怎么转移。

\(dp_i = true/false\)表示前i个数是否满足条件。
对所有的\(1\leq i\leq n\)有转移方程:
\(i - a_i - 1 >= 0,dp_i |= dp_{i - a_i - 1}\)
\(i + a_i <= n,dp_{i + a_i} |= dp_{i - 1}\)

int dp[200010];
void solve() {
    int n; cin >> n;
    vector<int> a(n + 1), pre[n + 1];
    memset(dp, 0, sizeof dp);
    for (int i = 1;i <= n;i++) cin >> a[i];
    dp[0] = 1;
    for (int i = 1;i <= n;i++) {
        if (i - a[i] - 1 >= 0) dp[i] |= dp[i - a[i] - 1];
        if (i + a[i] <= n) dp[i + a[i]] |= dp[i - 1];
    }

    cout << (dp[n] == 1 ? "YES\n" : "NO\n");
}

F

待补

G

待补

posted @ 2022-10-12 16:16  Coldarra  阅读(81)  评论(0)    收藏  举报