ZZJC 2024 autumn Individual Contest - 11(题解)

预测难度

Easy:A、C
Medium:E、B、F
Hard:D

实际难度

Easy:A、C
Medium:F、B
Hard:D、E

A - Debug

分析

错误存在第7行
s.length()s.size()返回的类型为unsigned long long,当有符号型整数遇到无符号整数时类型自动转换为无符号,因此i >= s.length() - k永远无法成立,导致程序陷入死循环。
此处应改为i >= (int)s.length() - k

代码实现

#include <bits/stdc++.h>

#ifdef LOCAL
#include "algo/debug.hpp"
#else
#define debug(...) 42
#endif

int main() {
    std::cin.tie(nullptr)->sync_with_stdio(false);
    std::cout << "Yes" << "\n";
    std::cout << 7 << '\n';
}

C - 两数之和

分析

由于n2105,如果进行双重循环遍历时间复杂为O(n2),显然会超时。
考虑优化,使用std::muiltiset进行存储和查询,查询和存取的时间复杂度为O(logn),对于每个数y进行遍历,如果std::muiltiset存在xy即输出YES,遍历结束后不存在即输出NO
同理也可以使用二分查找判断xy是否存在。
最终的复杂度均为O(nlogn)
注意判断存在重复的情况。

代码实现(multiset版)

#include <bits/stdc++.h>

#ifdef LOCAL
#include "algo/debug.hpp"
#else
#define debug(...) 42
#endif

int main() {
    std::cin.tie(nullptr)->sync_with_stdio(false);
    int n, x;
    std::cin >> n >> x;
    std::vector<int> a(n);
    std::multiset<int> st;
    for (int i = 0; i < n; ++i) {
        std::cin >> a[i];
        st.insert(a[i]);
    }
    for (int i = 0; i < n; ++i) {
        if (a[i] * 2 != x) {
            if (st.contains(x - a[i])) {
                std::cout << "YES" << '\n';
                return 0;
            }
        } else if (st.count(a[i]) > 1) {
            std::cout << "YES" << '\n';
            return 0;
        }
    }
    std::cout << "NO" << '\n';
}

代码实现(二分版)

#include <bits/stdc++.h>

#ifdef LOCAL
#include "algo/debug.hpp"
#else
#define debug(...) 42
#endif

int main() {
    std::cin.tie(nullptr)->sync_with_stdio(false);
    int n, x;
    std::cin >> n >> x;
    std::vector<int> a(n);
    for (int i = 0; i < n; ++i) {
        std::cin >> a[i];
    }
    std::sort(a.begin(), a.end());
    for (int i = 0; i < n; ++i) {
        int pos = std::ranges::lower_bound(a, x - a[i]) - a.begin();
        if (pos != n && a[pos] + a[i] == x && pos != i) {
            std::cout << "YES" << '\n';
            return 0;   
        }
    }
    std::cout << "NO" << '\n';
}

E - 排版

老东西看了这题应该很亲切吧,没错他又来了~

分析

本题主要难度在于如何处理字符串,对于若干行可以选择使用while(std::getline(std::cin, line))进行行读入。
对于空格的处理可以使用std::stringstream进行重载输入流,将读到的不含空格的字符串存入std::vector<std::string>数组中,最后按照题意处理即可。

代码实现

#include <bits/stdc++.h>

#ifdef LOCAL
#include "algo/debug.hpp"
#else
#define debug(...) 42
#endif

int main() {
    std::cin.tie(nullptr)->sync_with_stdio(false);
    std::string line;
    while (std::getline(std::cin, line)) {
        std::stringstream is(line);
        std::vector<std::string> v;
        std::string p;
        while (is >> p) {
            std::transform(p.begin(), p.end(), p.begin(), tolower);
            v.push_back(p);
        }
        for (int i = 0; i < size(v); ++i) {
            if (i == 0 || v[i - 1].back() == '.' || v[i] == "i," || v[i] == "i." || v[i] == "i") {
                v[i][0] -= 32;
            }
            std::cout << v[i] << " \n"[i == size(v) - 1];
        }
    }
}

B - Tree Degree Optimization

分析

贪心。在确保每个点都有入度d(即最终的图为一棵树而非森林)的情况下,每次添加(d2(d1)2)ai即可,一棵数的总度数为2n2

代码实现

#include <bits/stdc++.h>

#ifdef LOCAL
#include "algo/debug.h"
#else
#define debug(...) 42
#endif

int main() {
    std::cin.tie(nullptr)->sync_with_stdio(false);
    #define int long long
    int n;
    std::cin >> n;
    std::vector<int> a(n);
    for (int i = 0; i < n; ++i) {
        std::cin >> a[i];
    }
    int ans = 0;
    std::priority_queue<std::pair<int, int>, std::vector<std::pair<int, int>>, std::greater<>> q;
    for (int i = 0; i < n; ++i) {
        ans += a[i];
        q.emplace(3LL * a[i], 2);
    }
    for (int i = 1; i < n - 1; ++i) {
        auto [w, num] = q.top();
        q.pop();
        ans += w;
        q.emplace(w / (2 * num - 1) * (2 * num + 1), num + 1);
    }
    std::cout << ans << '\n';
}

F - Partition

分析

贪心,对k的大小进行分类讨论即可。
首先将所有的0取出放在最前面,随后进行分类讨论:
k>0时可以发现一定有解,将所有的负数从小到大插入,正数从大到小插入即可;
k=0时可以发现当i=1i=nai0时有解,此时将所有的正数从大到小插入,再将负数从小到大插入即可;
k<0时可以发现当i=1i=naik时有解,此时将所有的正数从大到小插入,再将负数从小到大插入即可。

代码实现

#include <bits/stdc++.h>
#ifdef LOCAL
#include "algo/debug.h"
#else
#define debug(...) 42
#endif
int main() {
    std::cin.tie(nullptr)->sync_with_stdio(false);
    #define int long long
    int n, k;
    std::cin >> n >> k;
    std::vector<int> a, b, c;
    for (int i = 0; i < n; ++i) {
        int x;
        std::cin >> x;
        if (x == 0) {
            c.push_back(x);
        } else if (x > 0) {
            a.push_back(x);
        } else {
            b.push_back(x);
        }
    }
    std::sort(a.rbegin(), a.rend()); // +
    std::sort(b.begin(), b.end()); // -
    int s = std::accumulate(a.begin(), a.end(), 0LL) + std::accumulate(b.begin(), b.end(), 0LL);
    if (k == 0) {
        if (s >= 0) {
            c.insert(c.end(), a.begin(), a.end());
            c.insert(c.end(), b.begin(), b.end());
            std::cout << "Yes" << "\n";
            for (int i = 0; i < n; ++i) {
                std::cout << c[i] << " \n"[i == n - 1];
            }
        } else {
            std::cout << "No" << '\n';
        }
    } else if (k < 0) {
        if (s >= k) {
            c.insert(c.end(), a.begin(), a.end());
            c.insert(c.end(), b.begin(), b.end());
            std::cout << "Yes" << "\n";
            for (int i = 0; i < n; ++i) {
                std::cout << c[i] << " \n"[i == n - 1];
            }
        } else {
            std::cout << "No" << "\n";
        }
    } else {
        c.insert(c.end(), b.begin(), b.end());
        c.insert(c.end(), a.begin(), a.end());
        std::cout << "Yes" << "\n";
        for (int i = 0; i < n; ++i) {
            std::cout << c[i] << " \n"[i == n - 1];
        }
    }
}

D - Conquer a New Region

分析

由于要让所有点到这个点的边权最小值之和最大,考虑把边按从大到小插入。
此时每次并入的边权值都是当前已并入边中最小的,那么只要判断并入哪个集合更优。
最后用并查集维护即可。

代码实现

#include <bits/stdc++.h>

#ifdef LOCAL
#include "algo/debug.hpp"
#else
#define debug(...) 42
#endif

#define int long long

struct DSU {
    std::vector<int> p, siz, d;
    DSU(int n) { init(n); }
    void init(int n) {
        p.resize(n);
        std::iota(p.begin(), p.end(), 0);
        siz.assign(n, 1);
        d.assign(n, 0);
    }
    int leader(int x) {
        while (x != p[x]) x = p[x] = p[p[x]];
        return x;
    }
    bool same(int x, int y) { return leader(x) == leader(y); }
    bool merge(int x, int y, int z) {
        x = leader(x), y = leader(y);
        if (x == y) return false;
        int dx = d[x] + siz[y] * z;
        int dy = d[y] + siz[x] * z;
        if (dx > dy) {
            d[x] = dx;
            siz[x] += siz[y], p[y] = x;
        } else {
            d[y] = dy;
            siz[y] += siz[x], p[x] = y;
        }
        return true;
    }
    int size(int x) { return siz[leader(x)]; }
    int dist(int x) { return d[leader(x)]; }
};

main() {
    std::cin.tie(nullptr)->sync_with_stdio(false);
    int n;
    while (std::cin >> n) {
        std::vector<std::array<int, 3>> edges(n - 1);
        for (auto &[c, a, b] : edges) {
            std::cin >> a >> b >> c;
            a--, b--;
        }
        std::sort(edges.rbegin(), edges.rend());
        DSU dsu(n);
        for (auto [c, a, b] : edges) {
            dsu.merge(a, b, c);
        }
        std::cout << dsu.dist(0) << '\n';
    }
}
posted @   sleeeeeping  阅读(49)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
  1. 1 吹梦到西洲 恋恋故人难,黄诗扶,妖扬
  2. 2 敢归云间宿 三无Marblue
吹梦到西洲 - 恋恋故人难,黄诗扶,妖扬
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.

作词 : 颀鞍

作曲 : 铃木航海

编曲 : 远藤直弥/冯帆

制作人 : 冯帆/铃木航海

(妖扬)

(妖扬)

无何化有 感物知春秋

秋毫濡沫欲绸缪 搦管相留

(黄诗扶)

留骨攒峰 留容映水秀

留观四时曾邂逅 佳人西洲

(妖扬)

(妖扬)

西洲何有 远树平高丘

云闲方外雨不收 稚子牵牛

(黄诗扶)

闹市无声 百态阴晴栩栩侔

藤衣半卷苔衣皱 岁月自无忧

(妖扬)

(妖扬)

驾马驱车 尚几程扶摇入画中 咫尺

(黄诗扶)

径曲桥横 精诚难通

(黄诗扶、妖扬)

(黄诗扶、妖扬)

盼你渡口 待你桥头

松香接地走

挥癯龙绣虎出怀袖

起微石落海连波动

描数曲箜篌线同轴

勒笔烟直大漠 沧浪盘虬

一纸淋漓漫点方圆透

记我 长风万里绕指未相勾

形生意成 此意 逍遥不游

(妖扬)

(妖扬)

日月何寿 江海滴更漏

爱向人间借朝暮 悲喜为酬

(黄诗扶)

种柳春莺 知它风尘不可救

绵绵更在三生后 谁隔世读关鸠

(妖扬)

(妖扬)

诗说红豆 遍南国未见人长久 见多少

(黄诗扶)

来时芳华 去时白头

(黄诗扶、妖扬)

(黄诗扶、妖扬)

忘你不舍 寻你不休

画外人易朽

似浓淡相间色相构

染冰雪先披琉璃胄

蘸朱紫将登金银楼

天命碧城灰土 刀弓褐锈

举手夜古泼断青蓝右

照我 萤灯嫁昼只影归洪流

身魂如寄 此世 逍遥不游

(黄诗扶)

(黄诗扶)

情一物 无木成林无水行舟

情一事 未算藏谋真还谬

情一人 积深不厚积年不旧

情一念 墨尽非空 百代飞白骤 划地为囚

(妖扬)

(妖扬)

蓝田需汲酒 惟琼浆能浇美玉瘦

至高者清难垢 至贵者润因愁

痴竭火 知她不能求

醉逢歌 知他不必候

只约灵犀过隙灵光暗相投

(黄诗扶、妖扬)

(黄诗扶、妖扬)

万籁停吹奏

支颐听秋水问蜉蝣

既玄冥不可量北斗

却何信相思最温柔

顾盼花发鸿蒙 怦然而梦

你与二十八宿皆回眸

系我 彩翼鲸尾红丝天地周

情之所至 此心 逍遥不游

吉他 : ShadOw

钢琴 : ShadOw

和声编写 : 冯帆

和声 : 黄诗扶

人声混音 : 徐志明

混音 : 冯帆

母带 : 冯帆

企划 : 三糙文化

出品公司 : Negia Entertainment Inc.

点击右上角即可分享
微信分享提示