ACM-协会第一次周赛

注意: \color{red}{注意:} 注意: 个人博客传送门

A. Rapids 学说话

思路:

  • 操作分为两步
    • 第一步:加 Start
    • 第二步:替换 GenshinImpact
  • 然后模拟即可

时间复杂度: O ( n ∗ m + n ∗ k + ( n / m ) ∗ l o g ( n / m ) ) O(n * m + n * k + (n/m) * log(n/m)) O(nm+nk+(n/m)log(n/m))

signed main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    std::string str = "GenshinImpact";

    int n;
    std::cin >> n;

    std::string s;
    std::cin >> s;

    int len = str.length();

    std::vector<int> p;
    for (int i = 0; i + len <= n; i++) {
        if (s.substr(i, len) == str) {
            p.push_back(i + len);
        }
    }

    std::sort(p.rbegin(), p.rend());

    for (int i = 0; i < p.size(); i++) {
        s.insert(p[i], "Start");
    }

    while (s.find(str) != std::string::npos) {
        for (int i = 0; i + len < s.size(); i++) {
            if (s.substr(i, len) == str) {
                s = s.substr(0, i) + "ACM" + s.substr(i + len);
                break;
            }
        }
    }
    std::cout << s << "\n";

    return 0;
}

Python 解法

n = input()
s = input()
print(str.replace(s, "GenshinImpact", "ACMStart"))

B. Rapids 学跳跃

思路:

  • 一定要跳到最后一个位置,所以最后一个位置一定要走。
  • 可以贪心的思考,一定要去掉前 n - 1 个位置中的最大的 m 个,这样使得结果一定是最小的。

时间复杂度: O ( n ) O(n) O(n)

void solve() {
    int n, m;
    std::cin >> n >> m;

	int a[n];
    for (int i = 0; i < n; i++) {
        std::cin >> a[i];
    }
    i64 ans = a[n - 1];
    std::sort(a, a + n - 1);
    for (int i = 0; i + m + 1 < n; i++) {
        ans += a[i];
    }
    std::cout << ans << "\n";
}

C. Rapids 学走路

思路:

  • 前缀和板子题,如果不懂,请学习前缀和

时间复杂度: O ( n ) O(n) O(n)

signed main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    int n, q;
    std::cin >> n >> q;

    int a[n] = {};
    for (int i = 0; i < n; i++) {
        std::cin >> a[i];
    }
    i64 s[n + 1] = {0};
    for (int i = 0; i < n; i++) {
        s[i + 1] = s[i] + a[i];
    }

    while (q--) { // O(1) 查询
        int l, r;
        std::cin >> l >> r;

        std::cout << s[r] - s[l - 1] << "\n";
    }

    return 0;
}

D. 图图的生存率

思路:

  • 直接暴力枚举所有情况,或者用数学推理一下
  • 这题赛时出现最多的就是 RE,很多同学几乎都没考虑除 0 的情况

时间复杂度: O ( 1 0 4 / 1 ) O(10^4 / 1) O(104/1)

解法一 (暴力):

void solve() {
    int m, a, b;
    std::cin >> m >> a >> b;

    int ans = 0;
    for (int i = 0; i <= 100; i++) {
        for (int j = 0; j <= 100; j++) {
            if (1LL * i * a + 1LL * j * b <= m) {
                ans = std::max(ans, i + 2 * j + 50);
            }
        }
    }
    std::cout << std::min(std::max(ans, 75), 100) << "%\n";
}

E. chen 和 cheer 的例会之路

思路:

  • 图论最短路板子题

  • 跑一遍 dijkstra 即可,注意爆 int

时间复杂度: O ( n 2 ) O(n^2) O(n2)

const int N = 5010;
int n, m, vis[N];
i64 mp[N][N], dist[N];

void dijstra(int u) {
    memset(dist, 0x3f, sizeof dist);
    dist[u] = 0;
    for (int i = 0; i + 1 < n; i++) {
        int t = -1;
        for (int j = 1; j <= n; j++) {
            if (!vis[j] && (t == -1 || dist[t] > dist[j])) {
                t = j;
            }
        }

        for (int j = 1; j <= n; j++) {
            dist[j] = std::min(dist[j], dist[t] + mp[t][j]);
        }
        vis[t] = true;
    }
}

signed main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    std::cin >> n >> m;
    memset(mp, 0x3f, sizeof mp);

    for (int i = 0; i < m; i++) {
        int u, v, w;
        std::cin >> u >> v >> w;

        mp[u][v] = std::min(mp[u][v], 1LL * w); // 双向边
        mp[v][u] = std::min(mp[v][u], 1LL * w);
    }

    int s, t;
    std::cin >> s >> t;

    dijstra(s);

    std::cout << dist[t] << "\n";

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值