AtCoder Beginner Contest 157

比赛链接:https://atcoder.jp/contests/abc157

A - Duplex Printing

题意

计算 $n$ 页的文档双面打印要用多少张纸。

题解

答案即 $\lceil \frac{n}{2} \rceil$ 。

代码

#include <bits/stdc++.h>
using namespace std;
int main() {
    int n; cin >> n;
    cout << (n + 1) / 2;
}

B - Bingo

题意

给出一个 $3\times3$ 的方格,方格中的数互不相同,给出 $n$ 个互不相同的数,判断其中在方格中出现的数是否位于方格的同一行、或同一列、或同一对角线中。

题解

模拟即可。

代码

#include <bits/stdc++.h>
using namespace std;
int main() {
    map<int, pair<int, int>> mp;
    int a[3][3] = {};
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 3; j++) {
            cin >> a[i][j];
            mp[a[i][j]] = {i, j};
        }
    }
    int row[3] = {};
    int col[3] = {};
    int diago[3] = {};
    int n; cin >> n;
    for (int i = 0; i < n; i++) {
        int x; cin >> x;
        if (mp.count(x)) {
            ++row[mp[x].first];
            ++col[mp[x].second];
            if (mp[x].first == mp[x].second) 
                ++diago[0];
            if (mp[x].first + mp[x].second == 2)
                ++diago[1];
        }
    }
    bool ok = false;
    for (int i = 0; i < 3; i++) {
        ok |= row[i] == 3;
        ok |= col[i] == 3;
        ok |= diago[i] == 3;
    }
    cout << (ok ? "Yes" : "No");
}

C - Guess The Number

题意

输出一个 $n$ 位长的最小数,要求每一指定位都为指定数字,除了 $0$ 以外不可以出现前导零。

题解

模拟即可。

代码

#include <bits/stdc++.h>
using namespace std;
int main() {
    int n, m; cin >> n >> m;
    bool ok = true;
    string ans(n, '0');
    bool used[n] = {};
    for (int i = 0; i < m; i++) {
        int s; cin >> s;
        char c; cin >> c;
        if (!used[s - 1]) {
            ans[s - 1] = c;
            used[s - 1] = true;
        } else if (ans[s - 1] != c) {
            ok = false;
        }
    }
    if (n > 1 and ans[0] == '0') {
        if (used[0]) ok = false;
        else ans[0] = '1';
    }
    cout << (ok ? ans : "-1");
}

D - Friend Suggestions

题意

$n$ 个人中有 $m$ 对朋友关系,$k$ 对敌对关系,如果两个人既不是朋友关系也不是敌对关系且在同一朋友链中,称二者为彼此的朋友候选人,计算每个人有多少个朋友候选人。

题解

在一个并查集中:一个人的朋友候选人 = 并查集的总人数  - 并查集中的朋友数 - 并查集中的敌对数 - 自己。

所以先读入朋友关系构造并查集,然后根据朋友关系和敌对关系计算需要减去的人数即可。

代码

参考自:lukelmouse

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 100;

int fa[N], size[N], ans[N];

int Find(int x) {
    return x == fa[x] ? x : fa[x] = Find(fa[x]);
}

void Union(int x, int y) {
    int fa_x = Find(x);
    int fa_y = Find(y);
    if (fa_x != fa_y) {
        fa[fa_y] = fa_x;
        size[fa_x] += size[fa_y];
    }
}

void Init() {
    iota(fa, fa + N, 0);
    fill(size, size + N, 1);
}

int main() { 
    Init();
    int n, m, k; cin >> n >> m >> k;
    for (int i = 0; i < m; i++) {
        int x, y; cin >> x >> y;
        Union(x, y);
        ++ans[x], ++ans[y];
    }
    for (int i = 0; i < k; i++) {
        int x, y; cin >> x >> y;
        if (Find(x) == Find(y))
            ++ans[x], ++ans[y];
    }
    for (int i = 1; i <= n; i++)
        cout << size[Find(i)] - ans[i] - 1 << ' ';
}

E - Simple String Queries

题意

给出一个长 $n$ 的小写字母串 $s$,回答 $q$ 次询问:

  • 将 $s_i$ 替换为小写字母 $c$
  • 在区间 $[l,r]$ 中有多少种字母

题解一

利用 $set$ 存储每个小写字母的位置,每次二分查找是否有位置位于 $[l,r]$ 。

代码

参考自:harish_49

#include <bits/stdc++.h>
using namespace std;

set<int> st[26];

int main() {
    int n; string s; cin >> n >> s;
    for (int i = 1; i <= n; i++)
        st[s[i - 1] - 'a'].insert(i);
    int q; cin >> q;
    for (int i = 0; i < q; i++) {
        int op; cin >> op;
        if (op == 1) {
            int j; char c; cin >> j >> c;
            st[s[j - 1] - 'a'].erase(j);
            st[c - 'a'].insert(j);
            s[j - 1] = c;
        } else {
            int l, r; cin >> l >> r;
            int ans = 0;
            for (int j = 0; j < 26; j++) {
                auto it = st[j].lower_bound(l);
                if (it != st[j].end() and *it <= r)
                    ++ans;
            }
            cout << ans << "\n";
        }
    }
}

题解二

为每个小写字母建立一个树状数组。

代码

参考自:zdragon

#include <bits/stdc++.h>
using namespace std;
const int N = 5e5 + 10;

int bit[N][26];

void update(int pos, int id, int val) {
    for (int i = pos; i <= N; i += i & (-i))
        bit[i][id] += val;
}

int query(int pos, int id) {
    int res = 0;
    for (int i = pos; i >= 1; i -= i & (-i))
        res += bit[i][id];
    return res;
}

int main() {
    int n; string s; cin >> n >> s;
    for (int i = 1; i <= n; i++) 
        update(i, s[i - 1] - 'a', 1);
    int q; cin >> q;
    for (int i = 0; i < q; i++) {
        int op; cin >> op;
        if (op == 1) {
            int j; char c; cin >> j >> c;
            update(j, s[j - 1] - 'a', -1);
            update(j, c - 'a', 1);
            s[j - 1] = c;
        } else {
            int l, r; cin >> l >> r;
            int ans = 0;
            for (int j = 0; j < 26; j++) 
                if (query(r, j) - query(l - 1, j))
                    ++ans;
            cout << ans << "\n";        
        }
    }
}

 

posted @ 2020-05-22 23:50  Kanoon  阅读(221)  评论(0)    收藏  举报