Codeforces Round 898 (Div. 4) 题解 | JorbanS

A-Short Sort

map<string, bool> mp;

string solve() {
    string s; cin >> s;
    if (mp[s]) return yes;
    return no;
}

int main() {
    mp["abc"] = mp["acb"] = mp["bac"] = mp["cba"] = true;
    Cases
    cout << solve() << endl;
    return 0;
}

B-Good Kid

int solve() {
    cin >> n;
    for (int i = 0; i < n; i ++) cin >> a[i];
    int res = 0;
    for (int i = 1; i <= n; i ++) {
        int t = 1;
        for (int j = 0; j < n; j ++)
            t *= a[j] + (j == i - 1);
        res = max(res, t);
    }
    return res;
}

C-Target Practice

int solve() {
    int res = 0;
    for (int i = 1; i <= 10; i ++) {
        char s[12]; cin >> s + 1;
        int dx = min(i, 11 - i);
        for (int j = 1; j <= 10; j ++)
            if (s[j] == 'X')
                res += min(dx, min(j, 11 - j));
    }
    return res;
}

D-1D Eraser

int solve() {
    int n, k; cin >> n >> k;
    string s; cin >> s;
    int res = 0;
    for (int i = 0; i < n; i ++)
        if (s[i] == 'B') i += k - 1, res ++;
    return res;
}

E-Building an Aquarium

int solve() {
    int n, x; cin >> n >> x;
    for (int i = 0; i < n; i ++) cin >> a[i];
    ll l = 0, r = 2e9;
    int res = 0;
    while (l < r) {
        ll mid = l + r + 1 >> 1, t = 0;
        for (int i = 0; i < n; i ++) t += max(0ll, mid - a[i]);
        if (t <= x) res = mid, l = mid;
        else r = mid - 1;
    }
    return res;
}

F-Money Trees

int solve() {
    int n, k; cin >> n >> k;
    for (int i = 1; i <= n; i ++) cin >> a[i];
    for (int i = 1; i <= n; i ++) cin >> h[i];
    int l = 1, r = 0, res = 0, cnt = 0;
    while (l <= n && r <= n) {
        while (r < n && cnt + a[r + 1] <= k && (l > r || h[r] % h[r + 1] == 0)) r ++, cnt += a[r];
        res = max(res, r - l + 1);
        if (cnt + a[r + 1] <= k) cnt = 0, l = r + 1;
        else cnt -= a[l], l ++;
    }
    return res;
}

G-ABBC or BACB

题意 给定一个只含字母 A , B A,B A,B 的字符串,问最多可以进行几次下列操作(每次任选其一)

  • 将连续的 A B AB AB 替换为 B C BC BC
  • 将连续的 B A BA BA 替换为 C B CB CB

题解

AA...AA BB AA...AA 可以将所有 A 消掉

AA...AA B AA...AA 只能选择消掉一边的 A,故贪心选择消掉较长的那边,即放弃较短的一边

AA...AA B AA...AA B AA...AA 始终有一段连续的 A 消不掉,即放弃最短的连续的 A 序列

当出现连续的 B 时,通过举例容易得出肯定能全部消掉, e . g . e.g. e.g. AAA BB AA B AAA B AA

int solve() {
    string s; cin >> s;
    int minn = 2e5, res = 0, cnt = 0;
    for (int i = 0; i < s.size(); i ++) {
        if (s[i] == 'A') {
            res ++;
            cnt ++;
        } else { // 连续的两次执行 else, 会使得 minn = 0
            minn = min(minn, cnt);
            cnt = 0;
        }
    }
    minn = min(minn, cnt);
    return res - minn;
}

H-Mad City

题意 n n n 个点 n n n 条边的无向连通图, A , B A,B A,B 的起点分别为 a , b a,b a,b A A A B B B,问 B B B 是否可能永远不会被 A A A 追到

当且仅当 A , B A,B A,B 在一个点或者同时经过同一条边时, A A A 抓到 B B B

基环树

基环树(基于环的树 ),也是环套树,是一种有 n n n 个点 n n n 条边的图,简单地讲就是树上在加一条边。它形如一个环,环上每个点都有一棵子树的形式

基环树的关键就是找到环,可以先把环当作这个无根树的“根” ,也就是把环当成一个点(先不管它),这样一颗基环树就变成了一个普通的树,然后我们先按照解决普通树的方法对“根”的所有子树依次处理求解答案,最后在单独对环上所有的点进行操作求解最终答案即可。

该图只有一个环,因此 B B B 要躲避 A A A 的追击,只要比 A A A 先到环上一点即可

环上最近的点的度数为 3 3 3,因此可用拓扑排序该点

d f s dfs dfs a , b a,b a,b 到环上一点的最短距离

string solve() {
    int n, a, b; cin >> n >> a >> b;
    vector<vector<int>> e(n + 1);
    vector<int> deg(n + 1);
    for (int i = 0; i < n; i ++) {
        int u, v; cin >> u >> v;
        e[u].push_back(v);
        e[v].push_back(u);
        deg[u] ++, deg[v] ++;
    }
    if (a == b) return no;
    // 拓扑排序
    queue<int> q;
    vector<bool> vis(n + 1);
    for (int i = 1; i <= n; i ++)
        if (deg[i] == 1) q.push(i);
    while (!q.empty()) {
        int t = q.front();
        q.pop();
        vis[t] = true;
        for (auto i : e[t]) {
            if (vis[i]) continue;
            deg[i] --;
            if (deg[i] == 1) q.push(i);
        }
    }
    // 求 b 点到任意点的最短距离
    for (int i = 1; i <= n; i ++) vis[i] = false;
    queue<pii> qq;
    qq.push({b, 0});
    int pos, dis;
    while (!qq.empty()) {
        pii t = qq.front();
        vis[t.aa] = true;
        qq.pop();
        if (deg[t.aa] != 1) {
            pos = t.aa, dis = t.bb;
            break;
        }
        for (auto i : e[t.aa])
            if (!vis[i]) qq.push({i, t.bb + 1});
    }
    // 求 a 点到任意点的最短距离
    for (int i = 1; i <= n; i ++) vis[i] = false;
    while (!qq.empty()) qq.pop();
    qq.push({a, 0});
    while (!qq.empty()) {
        auto t = qq.front();
        vis[t.aa] = true;
        qq.pop();
        if (t.aa == pos) {
            if (dis < t.bb) return yes;
            return no;
        }
        for (auto i : e[t.aa])
            if (!vis[i]) qq.push({i, t.bb + 1});
    }
    return yes;
}

你可能感兴趣的:(OI,题解,算法,图论,数据结构)