题解 | 牛客周赛 Round 126

A 小红的顺子构造

构造以 $x-4$ 为首的顺子即可,如果 $x-4<1$ ,就以 $\text{1}$ 为首。

void solve() {
    int x;
    cin >> x;
    int l = max(x - 4, 1);
    for (int i = l; i <= l + 4; ++i)
        cout << i << " ";
    cout << endl;
}

B 小红的字符串构造(easy)

因为保证两两有前缀关系。排序一遍,如果第 $k$ 个字符串是前缀,那么前 $k-1$ 个字符串同样是前缀。所以我们需要检查第 $k$ 个和第 $k+1$ 个,如果二者相等,那么当满足第 $k$ 个是前缀时,必然满足第 $k+1$ 个也是前缀,于是无法构造。

void solve() {
    int n, k;
    cin >> n >> k;
    vector<string> a(n);
    for (int i = 0; i < n; ++i) {
        cin >> a[i];
    }
    sort(all(a));
    if (k == n) {
        cout << a[n - 1] << endl;
    } else {
        if (a[k - 1].size() == a[k].size()) {
            cout << -1 << endl;
        } else {
            cout << a[k - 1] << endl;
        }
    }
}

C 小红的好数组构造

如果 $n-k$ 为奇数,删去 $k$ 个字符后剩余的字符中,肯定有一个字符出现了奇数次。

剩余的情况,我们可以构造 $k$ 个不同的数字 $\text{+}$ $n-k$ 个 $\text{1}$ 。

void solve() {
    int n, k;
    cin >> n >> k;
    if ((n - k) & 1) {
        cout << -1 << endl;
        return;
    }
    for (int i = 2; i <= k + 1; ++i)
        cout << i << " ";
    for (int i = 0; i < n - k; ++i)
        cout << 1 << " ";
    cout << endl;
}

D 小红的左看右看构造

先检查 $c$ 和 $d$ 的最后一个元素是否相等,这个是数组的最大值。

我们从左到右直接放 $c$ 的前 $x-1$ 个元素,从右到左直接放 $d$ 的前 $y-1$ 个元素,中间放最后一个元素,剩下的空位随便放小的数字即可。

注意这种构造方式至少需要 $x+y-1$ 个元素。

void solve() {
    int x, y, n;
    cin >> x >> y >> n;
    int c, d;
    vector<int> ans(n);
    for (int i = 0, t; i < x; ++i) {
        cin >> t;
        if (i < x - 1)
            ans[i] = t;
        else
            c = t;
    }
    for (int i = 0, t; i < y; ++i) {
        cin >> t;
        if (i < y - 1)
            ans[n - 1 - i] = t;
        else
            d = t;
    }
    if (c != d) {
        cout << -1 << endl;
        return;
    }
    if (x + y - 1 > n) {
        cout << -1 << endl;
        return;
    }
    ans[x - 1] = c;
    int i = x;
    while (!ans[i])
        ans[i++] = 1;
    for (int i = 0; i < n; ++i)
        cout << ans[i] << " ";
    cout << endl;
}

E 小红的完全平方数构造

小白月赛 Round 126 E 一样的思路。我们只需要找到 $x$ 使得 $n\times 10^L \leq x< (n+1)\times 10^L$ 即可。

void solve() {
    ll n;
    cin >> n;
    ll a = 10;
    for (int i = 0; i <= 10; ++i) {
        ll x = n * a;
        ll l = 1, r = 1e9, d = r;
        while (l <= r) {
            ll mid = (l + r) >> 1;
            if (mid * mid >= n * a)
                d = mid, r = mid - 1;
            else
                l = mid + 1;
        }
        if (d * d < (n + 1) * a) {
            cout << d * d << endl;
            return;
        }
        a *= 10;
    }
}

F 小红的基环树染色构造

先利用拓扑排序找环,环我们用 $1212…$ 的方式来染色,如果环的长度为奇数,就再加一个 $3$ 。然后对于环上延伸出去的每棵子树,我们都让子节点与父节点颜色不同即可。

void solve() {
    int n;
    cin >> n;
    vector<vector<int>> g(n + 1);
    vector<int> deg(n + 1);
    for (int i = 0; i < n; ++i) {
        int u, v;
        cin >> u >> v;
        g[u].pb(v), g[v].pb(u);
        deg[u]++, deg[v]++;
    }

    vector<int> vis(n + 1);
    queue<int> q;
    for (int i = 1; i <= n; ++i)
        if (deg[i] == 1)
            q.push(i);

    while (q.size()) {
        auto u = q.front();
        q.pop();

        vis[u] = 1;
        for (auto v : g[u]) {
            if (deg[v] > 1) {
                deg[v]--;
                if (deg[v] == 1)
                    q.push(v);
            }
        }
    }
    vector<int> cyc;
    int st = 0;
    for (int i = 1; i <= n; ++i) {
        if (!vis[i]) {
            st = i;
            break;
        }
    }

    int cur = st;
    vector<bool> vis2(n + 1);

    while (1) {
        cyc.pb(cur);
        vis2[cur] = true;

        int nxt = 0;
        for (int v : g[cur]) {
            if (!vis[v] && !vis2[v]) {
                nxt = v;
                break;
            }
        }

        if (nxt != 0) {
            cur = nxt;
        } else {
            break;
        }
    }

    vector<int> a(n + 1);
    int k = cyc.size();
    for (int i = 0; i < k; ++i) {
        int u = cyc[i];
        if (i < k - 1) {
            a[u] = (i % 2) + 1;
        } else {
            for (int c = 1; c <= 3; ++c) {
                if (c != a[cyc[i - 1]] && c != a[cyc[0]]) {
                    a[u] = c;
                    break;
                }
            }
        }
    }

    queue<int> q2;
    for (int u : cyc) {
        q2.push(u);
    }

    while (!q2.empty()) {
        int u = q2.front();
        q2.pop();

        for (int v : g[u]) {
            if (a[v] == 0) {
                for (int c = 1; c <= 3; ++c) {
                    if (c != a[u]) {
                        a[v] = c;
                        break;
                    }
                }
                q2.push(v);
            }
        }
    }

    for (int i = 1; i <= n; ++i) {
        cout << a[i] << " ";
    }
    cout << endl;
}

G 小红的字符串构造(hard)

构建一棵 $\text{Trie}$ 树,用 $end[i]$ 记录有多少个字符串恰好在此结束,我们只要找到一个节点,使得根节点到它的路径上 $end$ 之和恰好等于 $k$ 即可。

void solve() {
    int n, k;
    cin >> n >> k;
    Trie tr(maxn);
    for (int i = 0; i < n; ++i) {
        string s;
        cin >> s;
        tr.insert(s);
    }

    int tar = tr.find(0, 0, k);

    if (tar != -1) {
        cout << tr.get(tar) << endl;
    } else {
        cout << -1 << endl;
    }
}

头文件

#include <bits/stdc++.h>
#define pb push_back
#define eb emplace_back
#define fi first
#define se second
#define all(a) a.begin(), a.end()
#define rall(a) a.rbegin(), a.rend()
#define endl "\n"
using namespace std;

using ll = long long;
using ld = long double;
using ull = unsigned long long;
using i128 = __int128;
using PII = pair<int, int>;
using PLL = pair<ll, ll>;
using TIII = tuple<int, int, int>;
using TLLL = tuple<ll, ll, ll>;

constexpr int inf = (ll)1e9 + 7;
constexpr ll INF = (ll)2e18 + 9;
// constexpr ll INF = (ll)4e18;
// constexpr ll MOD = 1e9 + 7;
constexpr ll MOD = 998244353;
constexpr ld eps = 1e-10;

void init() {}

void solve() {}

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);

    init();

    int t = 1;
    cin >> t;
    for (int _ = 1; _ <= t; ++_) {
        solve();
    }

    return 0;
}

Trie 树

struct Trie {
    vector<array<int, 2>> ch;
    vector<int> end, fa, val;
    int idx = 0;

    Trie(int n) : ch(n), end(n), fa(n), val(n) {}

    void insert(string s) {
        int u = 0;
        for (char c : s) {
            int v = c - '0';
            if (!ch[u][v]) {
                ch[u][v] = ++idx;
                ch[idx][0] = ch[idx][1] = 0;
                end[idx] = 0;
                fa[idx] = u;
                val[idx] = v;
            }
            u = ch[u][v];
        }
        end[u]++;
    }

    int find(int u, int cur, int k) {
        cur += end[u];

        if (cur == k && u != 0) {
            return u;
        }

        if (cur > k) {
            return -1;
        }

        for (int v = 0; v < 2; ++v) {
            if (ch[u][v]) {
                int res = find(ch[u][v], cur, k);
                if (res != -1)
                    return res;
            }
        }

        return -1;
    }
    string get(int u) {
        string res = "";
        while (u > 0) {
            res += to_string(val[u]);
            u = fa[u];
        }
        reverse(all(res));
        return res;
    }
};
暂无评论

发送评论 编辑评论


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