AcWing第1场周赛题解

A. AcWing 3577. 选择数字

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

题目大意:从两个数组种各选出一个数,使它们的和不包含在两个数列中。

解题思路:因为元素都是正整数,所以找最大值即可。

示例程序:

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

int mx() {
    int n, a, res = 0;
    cin >> n;
    for (int i = 0; i < n; i++) {
        cin >> a;
        res = max(res, a);
    }
    return res;
}

int n, m, a[101], b[101];

int main() {
    cout << mx() << " " << mx() << endl;
    return 0;
}

B. AcWing 3578. 最大中位数

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

题目大意:进行k次+1操作使中位数最大。

解题思路:贪心,不用管较小的 $\lfloor \frac{n}{2} \rfloor $ 个数,每次从较大的 \(\lceil \frac{n}{2} \rceil\) 个数中选择一个最小的执行 \(+1\) 操作。但是单独加不好,可以模拟或者二分答案。

示例程序:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 5;
int n, k, a[maxn];

bool check(int m) {
    int c = k;
    for (int i = n/2; i < n; i++) {
        if (a[i] < m) {
            c -= m - a[i];
            if (c < 0)
                return false;
        }
        else return true;
    }
    return true;
}

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);
    cin >> n >> k;
    for (int i = 0; i < n; i++) cin >> a[i];
    sort(a, a+n);
    int l = a[n/2], r = a[n/2] + k, res;
    while (l <= r) {
        int mid = l + (r - l) / 2;
        if (check(mid)) {
            res = mid;
            l = mid + 1;
        } else r = mid - 1;
    }
    cout << res << endl;
    return 0;
}

C. AcWing 3579. 数字移动

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

题目大意:找每个数多少次能变回自己。

解题思路:找环, \(i \rightarrow p_i\) 一条边,判断每个点所在的有向环长度。搜索。

示例程序:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 5;
int T, n, p[maxn], bl[maxn], dis[maxn]; // bl[i]表示搜索起点编号,dis[s]表示s所在环长度

void dfs(int u, int s, int d) { // u当前节点,s搜索起点
    bl[u] = s;
    if (p[u] == s) {
        dis[s] = d;
        return;
    }
    dfs(p[u], s, d+1);
}

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);
    cin >> T;
    while (T--) {
        cin >> n;
        for (int i = 1; i <= n; i++) cin >> p[i];
        memset(bl, 0, sizeof(int)*(n+1));
        for (int i = 1; i <= n; i++)
            if (!bl[i])
                dfs(i, i, 1);
        for (int i = 1; i <= n; i++) {
            if (i > 1) cout << " ";
            cout << dis[bl[i]];
        }
        cout << endl;
    }
    return 0;
}

补充:今天出数据发现 dfs 解法可能会爆栈(dfs深度过高),所以更新一种 bfs 解法,如下:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 5;
int T, n, p[maxn], bl[maxn], dis[maxn]; // bl[i]表示搜索起点编号,dis[s]表示s所在环长度

void bfs(int s) { // u当前节点,s搜索起点
    for (int u = s, d = 1; ; u = p[u], d++) {
        bl[u] = s;
        if (p[u] == s) {
            dis[s] = d;
            break;
        }
    }
}

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);
    cin >> T;
    while (T--) {
        cin >> n;
        for (int i = 1; i <= n; i++) cin >> p[i];
        memset(bl, 0, sizeof(int)*(n+1));
        for (int i = 1; i <= n; i++)
            if (!bl[i])
                bfs(i);
        for (int i = 1; i <= n; i++) {
            if (i > 1) cout << " ";
            cout << dis[bl[i]];
        }
        cout << endl;
    }
    return 0;
}
posted @ 2022-04-07 09:38  quanjun  阅读(34)  评论(0编辑  收藏  举报