AcWing第四场周赛

比赛链接:Here

AcWing 3694. A还是B

签到题

void solve() {
    int n; string s;
    cin >> n >> s;
    int t = count(s.begin(), s.end(), 'A');
    if (t * 2 == n)cout << "T";
    else if (t * 2 < n)cout << "B";
    else cout << "A";
}

AcWing 3695. 扩充序列

思维构造题

这题目本身并不难,只不过出得有 一些 “委婉”罢了。

先来研究一下题目,每次“扩充”都会将序列复制一次,然后在中间会插入一个还未使用过的最小正整数。

其实“还未使用过的 最小 正整数”,其实不过就是添加原数列中最大的值+1。

再看,扩充 \(n\) 次,就会将原序列变为 \(2^n + 1\)

那么对于 \(k\) 来说,只需判断小于 \(2^x\) 即可

输出 \(x + 1\)

注意点:long long

void solve() {
    ll n, k; cin >> n >> k;
    int cnt = 1;
    while (!(k & 1))k >>= 1, cnt++;
    cout << cnt << "\n";
}

AcWing 3696. 构造有向无环图

对图进行拓扑排序,其中我们只加有向边,不考虑无向边。

若无法拓扑排序,则说明有向边已经构成了环,输出 NO。

否则,在拓扑排序的时候,对于所有点,我们可以得到一个时间戳,而对于所有无向边,将其方向定位从时间戳小的连向时间戳大的边即可。

时间复杂度:\(\mathcal{O}(n + m)\)

typedef pair<int, int> E;
const int N = 200005;
int n, m;
int d[N], p[N];
vector<int> g[N];
bool topo() {
    static int q[N], hh, tt, s;
    hh = tt = 0, s = 0;
    for (int x = 1; x <= n; ++x)
        if (!d[x]) q[tt++] = x;
    while (hh != tt) {
        int t = q[hh++];
        ++s, p[t] = s;
        for (int i = 0; i < g[t].size(); ++i) {
            int v = g[t][i];
            if (!--d[v]) q[tt++] = v;
        }
    }
    return s == n;
}
void solve() {
    cin >> n >> m;
    memset(d + 1, 0, n << 2);
    memset(p + 1, 0, n << 2);
    for (int i = 1; i <= n; ++i) g[i].clear();
    vector<E> res;
    for (int i = 0; i < m; ++i) {
        int a, b, t;
        cin >> t >> a >> b;
        res.push_back({a, b});
        if (t) g[a].push_back(b), ++d[b];
    }
    if (topo()) {
        puts("YES");
        for (auto [a, b] : res) {
            if (p[a] > p[b]) swap(a, b);
            printf("%d %d\n", a, b);
        }
    } else puts("NO");

}
posted @ 2021-07-06 15:45  RioTian  阅读(39)  评论(0编辑  收藏  举报