AcWing第4场周赛题解

A. AcWing 3694. A还是B

题目链接:https://www.acwing.com/problem/content/3697/

题目大意:判断字符串中'A'还是'B'出现地多。

解题思路:循环一遍记个数。

示例程序:

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

string s;
int n, a, b;

int main() {
    cin >> n >> s;
    for (auto c : s)
        (c == 'A') ? a++ : b++;
    if (a == b) puts("T");
    else if (a > b) puts("A");
    else puts("B");
    return 0;
}

AcWing 3695. 扩充序列

题目链接:https://www.acwing.com/problem/content/3698/

题目大意:求序列扩充n次的第k个数。

解题思路:可以基于分治用递归做,也可以用二进制做。因为这道题是cf原题,我递归写过了,所以这里用二进制做,但其实都是基于分治思想。

示例程序:

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

int n;
long long k;

int main() {
    cin >> n >> k;
    for (int i = n-1; i >= 0; i--) {
        if (!(k ^ (1LL<<i))) {
            cout << i+1 << endl;
            break;
        }
        k &= (1LL<<i)-1;
    }
    return 0;
}

C. AcWing 3696. 构造有向无环图

题目链接:https://www.acwing.com/problem/content/3699/

题目大意:给图上一些边确定方向,使其成为一个 DAG。

解题思路:拓扑排序两次,第一次给每个节点一个时间戳,然后根据时间戳的大小(小的往大的连一条边),第二次(连好边后)看看能不能正常拓扑排序,可以的话就 “YES”;不然就 “NO”。

示例程序:

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

int T, n, m, t[maxn], x[maxn], y[maxn], in[maxn], tt[maxn]; // tt[i]表示节点i的时间戳
vector<int> g[maxn];
queue<int> que;

bool check() {
    int idx = 0;    // 时间戳
    while (!que.empty()) que.pop();
    for (int i = 1; i <= n; i++) if (!in[i]) {
        tt[i] = ++idx;
        que.push(i);
    }
    while (!que.empty()) {
        int u = que.front();
        que.pop();
        for (auto v : g[u]) {
            in[v]--;
            if (!in[v]) {
                tt[v] = ++idx;
                que.push(v);
            }
        }
    }
    return idx == n;
}

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);
    cin >> T;
    while (T--) {
        cin >> n >> m;
        for (int i = 0; i < m; i++)
            cin >> t[i] >> x[i] >> y[i];
        // 1-st topological sorting
        for (int i = 1; i <= n; i++) g[i].clear(), in[i] = 0;
        for (int i = 0; i < m; i++)
            if (t[i]) g[x[i]].push_back(y[i]), in[y[i]]++;
        if (!check()) {
            cout << "NO" << endl;
            continue;
        }
        // 根据原来的有向边及时间戳重新建图
        for (int i = 1; i <= n; i++)
            g[i].clear();
        for (int i = 0; i < m; i++) {
            int u = x[i], v = y[i];
            if (!t[i] && tt[u] > tt[v]) swap(u, v);
            g[u].push_back(v);
            in[v]++;
        }
        // 2-st topological sorting
        if (!check()) {
            cout << "NO" << endl;
        } else {
            cout << "YES" << endl;
            // 输出边的信息
            for (int i = 0; i < m; i++) {
                int u = x[i], v = y[i];
                if (!t[i] && tt[u] > tt[v]) swap(u, v);
                cout << u << " " << v << endl;
            }
        }
    }
    return 0;
}
posted @ 2022-04-07 14:41  quanjun  阅读(97)  评论(0编辑  收藏  举报