题解 | 牛客周赛 Round 131

先提前祝大家新年快乐。

A ICPC Balloons

判一下就行

void solve() {
    string s;
    cin >> s;
    if (s == "A")
        cout << "red" << endl;
    if (s == "B")
        cout << "orange" << endl;
    if (s == "C")
        cout << "blue" << endl;
    if (s == "D")
        cout << "green" << endl;
}

B String Covering

不难发现,只有单个 $1$ 是染不出来的。

void solve() {
    int n;
    string s;
    cin >> n >> s;
    int cnt = 0;
    for (auto v : s) {
        if (v == '1')
            cnt++;
        else {
            if (cnt == 1) {
                cout << "NO" << endl;
                return;
            }
            cnt = 0;
        }
    }
    if (cnt == 1) {
        cout << "NO" << endl;
    } else {
        cout << "YES" << endl;
    }
}

C Get The Sequence

贪心匹配即可,如果 $a[i]>b[ptr]$ ,就匹配上了,否则换下一个 $a[i+1]$ 继续匹配。

void solve() {
    int n, m;
    cin >> n >> m;
    vector<int> a(n), b(m);
    for (int i = 0; i < n; ++i)
        cin >> a[i];
    for (int i = 0; i < m; ++i)
        cin >> b[i];
    int ptr = 0;
    for (int i = 0; i < n; ++i) {
        if (ptr == m)
            break;
        if (a[i] >= b[ptr]) {
            ptr++;
        }
    }
    if (ptr == m)
        cout << "YES" << endl;
    else
        cout << "NO" << endl;
}

D Longest Subsequence

也就是求最长子序列,我们用 $dp[x]$ 记录以 $x$ 为结尾的最长子序列长度,它只能从 $x-1$ 或 $x+1$ 演变过来,显然有
$$
dp[x] = \max(dp[x],\max(dp[x-1],dp[x+1])+1)
$$

void solve() {
    int n;
    cin >> n;
    unordered_map<int, int> dp;
    int ans = 0;
    for (int i = 0, x; i < n; ++i) {
        cin >> x;
        dp[x] = max(dp[x], max(dp[x - 1], dp[x + 1]) + 1);
        ans = max(ans, dp[x]);
    }
    cout << ans << endl;
}

E Eat The Candy

一个盒子的糖果参与了合并,对于这个盒子一定是不优的(最优的情况也就是拿出一个合并,然后获取一个新产生的糖果)。所以显然合并出来的新糖放到同一个盒子里是最优的,且那个盒子不能进行合并。合并可以从两边向中间贪心匹配(两边向中间能合并就合并),也就是如果最后第 $i$ 个盒子糖果最多,就是它原本的糖果数 $+$ 左边新生成的糖果数 $+$ 右边新生成的糖果数。

左边的糖果数在枚举过程中动态计算即可,右边的可以用一个后缀数组预先算好。

void solve() {
    int n;
    cin >> n;
    vector<ll> a(n + 1);
    for (int i = 1; i <= n; ++i)
        cin >> a[i];
    vector<ll> suf(n + 2);

    ll rem = a[n];
    for (int i = n - 1; i >= 1; --i) {
        ll ops = min(a[i], rem);
        suf[i] = suf[i + 1] + ops;
        rem = a[i] - ops;
    }

    ll ans = 0, S = 0;
    rem = 0;
    for (int i = 1; i <= n; ++i) {
        ll cur = a[i] + S + suf[i + 1];
        if (cur > ans)
            ans = cur;
        ll ops = min(rem, a[i]);
        S += ops;
        rem = a[i] - ops;
    }
    cout << ans << endl;
}

F Bracket Coloring

两个典题揉一块造出来的典题。

先是括号匹配,直接用栈模拟一下即可。如果把每一组括号看成一个节点,那么如果相邻两个字符相同,他们所属的节点之间就要连一条边,然后你就会发现,我趣,原来是无向图的 $2$ 色染色问题。

那么每一个连通分量都有两种染色方式,答案就是 $2^{\text{连通分量个数}}$ 。

因为我是超级懒狗,所以直接用 $\text{DSU}$ 维护了(你用其他方式求连通分量都是可以的)。

void solve() {
    int n;
    string s;
    cin >> n >> s;
    vector<int> pid(n), stk;
    int id = 0;
    for (int i = 0; i < n; i++) {
        if (s[i] == '(')
            stk.pb(i);
        else {
            int l = stk.back();
            stk.pob();
            ++id;
            pid[l] = pid[i] = id;
        }
    }
    DSU dsu(id);
    for (int i = 0; i + 1 < n; i++) {
        if (s[i] == s[i + 1]) {
            int u = pid[i], v = pid[i + 1];
            if (u != v)
                dsu.merge(u, v);
        }
    }

    vector<bool> vis(id + 1);
    int c = 0;
    for (int i = 1; i <= id; i++) {
        int rt = dsu.find(i);
        if (!vis[rt]) {
            vis[rt] = 1;
            c++;
        }
    }
    cout << ksm(Z(2), c) << endl;
}
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇