2025年第七届传智杯程序设计挑战赛复赛(第二场)补题

E-小苯的水瓶

原题:E-小苯的水瓶

题意:

给定 n 个水瓶,每个水瓶有一些水,这些水瓶可以倒水给其他水瓶,但是转移的总和不能超过 m,可以操作任意次,此外还有 k 的水量可以分配给这些水瓶,最后小红会喝掉水量最少的水瓶里的水,问小红最多可以喝多少水

思路:

如果 小红最多能喝 h 的水,那么 h-1, h-2 .... 比 h 少的水量他肯定可以喝到这么多水,满足单调性,可以二分。

check 函数就是把 < limit 的水瓶需要的水量全部加起来,记为 need,另外把多的加起来记为 res,再加上 k,看 need 与 min(res,m)+k 的大小

//      https://ac.nowcoder.com/acm/contest/103864/E

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int MOD = 1e9 + 7;

int T, n, m, k;
int a[200005];

bool check(int limit)
{
    int res = 0, need = 0;
    for (int i = 0; i < n; i++)
    {
        if (a[i] < limit)
            need += limit - a[i];
        else
            res += a[i] - limit;
    }
    res = min(res, m);
    return need <= res + k;
}

void solve()
{
    cin >> n >> m >> k;
    int mx = 0;
    for (int i = 0; i < n; i++)
        cin >> a[i], mx = max(mx, a[i]);
    // sort(a,a+n);
    int l = 0, r = mx + k / n + 1, ans;
    while (l <= r)
    {
        int mid = (r - l) / 2 + l;
        if (check(mid))
            l = mid + 1, ans = mid;
        else
            r = mid - 1;
    }
    cout << ans << "\n";
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    T = 1;
    cin >> T;
    while (T--)
    {
        solve();
    }
    return 0;
}

D-小苯的ovo

原题:D-小苯的ovo

题意:

给定一个只包含 'o'、'v' 的字符串,最多能进行 K 次以下操作:

  • 将 'o' -> 'v' 或者 'v' -> 'o'

问最后子串 "ovo" 的数量(字串之间互相独立)

思路:

dp

dp[ i ][ j ] 表示前 i 个位置,花费 j 次操作的最大数量

//      https://ac.nowcoder.com/acm/contest/103864/D

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int MOD = 1e9 + 7;

int T, n, m, k;
void solve()
{
    cin >> n >> k;
    string s;
    cin >> s;
    vector<vector<int>> dp(n + 1, vector<int>(k + 1, 0));
    int ans = 0;
    for (int i = 3; i <= n; i++)
    {
        for (int j = 0; j <= k; j++)
        {
            dp[i][j] = dp[i - 1][j];
            int cnt = 0;
            if (s[i - 1] != 'o')
                cnt++;
            if (s[i - 2] != 'v')
                cnt++;
            if (s[i - 3] != 'o')
                cnt++;
            if (j >= cnt)
                dp[i][j] = max(dp[i - 3][j - cnt] + 1, dp[i][j]);
            // ans = max(ans, dp[i][j]);
        }
    }
    cout << dp[n][k] << "\n";
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    T = 1;
    cin >> T;
    while (T--)
    {
        solve();
    }
    return 0;
}

G-小苯的奇怪最短路

原题:G-小苯的奇怪最短路

题意:

定义最短路:从 1 -> n 的边中 最大值 + 最小值,求 1 -> n 的最短路

思路:

最小生成树 + 并查集

最小生成树求连通图的过程中再开一个 min 数组用来存每个集合的最小边,如果 1 和 n 连通了,那么最大值的边就是现在这条边,因为 K 算法求最小生成树就是将边按边权从小到大排好序了,那么答案就是 min[f[1]] + 当前的边的权值

//      https://ac.nowcoder.com/acm/contest/103864/G

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

int t, n, m;
int find(vector<int> &f, int a)
{
    if (a != f[a])
        f[a] = find(f, f[a]);
    return f[a];
}

void Union(vector<int> &f, vector<int> &mi, int a, int b, int w)
{
    int fa = find(f, a);
    int fb = find(f, b);
    f[fb] = fa;
    mi[fa] = min(mi[fa], min(mi[fb], w));
}
void solve()
{
    cin >> n >> m;
    vector<vector<int>> v(m, vector<int>(3));
    vector<int> f(n + 1, 0), mi(n + 1, 1e18);
    for (int i = 0; i <= n; i++)
        f[i] = i;
    for (int i = 0; i < m; i++) // m条边
        cin >> v[i][0] >> v[i][1] >> v[i][2];

    // 按边的权值从小到大排序
    sort(v.begin(), v.end(), [](const vector<int> &v1, const vector<int> &v2)
         { return v1[2] < v2[2]; });
    int ans = 1e18;
    for (int i = 0; i < m; i++)
    {
        Union(f, mi, v[i][0], v[i][1], v[i][2]);
        if (find(f, 1) == find(f, n))
        {
            ans = min(ans, mi[find(f, 1)] + v[i][2]); // 因为边按大小已经排好序了,所以现在的 v[i][2] 就是目前的最大边
        }
    }
    cout << (ans == 1e18 ? -1 : ans) << "\n";
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    t = 1;
    cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}
#牛客创作赏金赛#
全部评论

相关推荐

05-11 11:48
河南大学 Java
程序员牛肉:我是26届的双非。目前有两段实习经历,大三上去的美团,现在来字节了,做的是国际电商的营销业务。希望我的经历对你有用。 1.好好做你的CSDN,最好是直接转微信公众号。因为这本质上是一个很好的展示自己技术热情的证据。我当时也是烂大街项目(网盘+鱼皮的一个项目)+零实习去面试美团,但是当时我的CSDN阅读量超百万,微信公众号阅读量40万。面试的时候面试官就告诉我说觉得我对技术挺有激情的。可以看看我主页的美团面试面经。 因此花点时间好好做这个知识分享,最好是单拉出来搞一个板块。各大公司都极其看中知识落地的能力。 可以看看我的简历对于博客的描述。这个帖子里面有:https://www.nowcoder.com/discuss/745348200596324352?sourceSSR=users 2.实习经历有一些东西删除了,目前看来你的产出其实很少。有些内容其实很扯淡,最好不要保留。有一些点你可能觉得很牛逼,但是面试官眼里是减分的。 你还能负责数据库表的设计?这个公司得垃圾成啥样子,才能让一个实习生介入数据库表的设计,不要写这种东西。 一个公司的财务审批系统应该是很稳定的吧?为什么你去了才有RBAC权限设计?那这个公司之前是怎么处理权限分离的?这些东西看着都有点扯淡了。 还有就是使用Redis实现轻量级的消息队列?那为什么这一块不使用专业的MQ呢?为什么要使用redis,这些一定要清楚, 就目前看来,其实你的这个实习技术还不错。不要太焦虑。就是有一些内容有点虚了。可以考虑从PR中再投一点产出
点赞 评论 收藏
分享
评论
2
2
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务