codeforces round 936 div2(a,b,c)

文章讨论了三个编程问题:1)给定数组,计算使其中位数变大的最小操作次数;2)给定数组和插入操作,求操作后最大和;3)在树中,找到删除k条边后每个区块最少节点数。涉及排序、连续子数组求和和图论方法。
摘要由CSDN通过智能技术生成

快一个月没做题了…果然vp的依托,加快训练吧
比赛链接

A

题目大意

给定 n n n个元素的数组 a a a,每次操作可以选择一个元素并让其加 1 1 1,问使得数组中位数(像上取整)变大的最小操作次数为多少

思路

先排序。每次操作让数字变大,中位数是否只与等于自己的有关,统计输出

ACcode

#include<bits/stdc++.h>

using namespace std;

#define int long long

void solve()
{
    int n;cin >> n;
    vector<int>a(n + 3);
    for (int i = 1;i <= n;i++)cin >> a[i];
    sort(a.begin() + 1, a.begin() + 1 + n);
    int mid = n / 2;
    if (n & 1)mid++;
    int mm = mid;
    int num = 0;
    while (a[mid] == a[++mm] && mm <= n)num++;
    cout << num + 1 << '\n';
}

signed main()
{
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    int t;cin >> t;
    while (t--) {
        solve();
    }
    return 0;
}

B

题目大意

给定 n n n个元素的数组 a a a,给定 k k k次操作,每次操作找到 a a a的连续任意子数组(可以是 0 0 0),并在 a a a中任意位置插入连续子数组的和,找到输出 k k k次操作之后的数组 a a a的最大和(结果对 1 e 9 + 7 1e9+7 1e9+7取模)

思路

求数组内连续元素的和的最大值,叠加即可

ACcode

#include<bits/stdc++.h>

using namespace std;

#define int long long

const int M = 1e9 + 7;

void solve()
{
    int n, k;cin >> n >> k;
    vector<int>a(n + 9);
    int sum = 0;
    for (int i = 1;i <= n;i++)cin >> a[i], sum += a[i], a[i] += a[i - 1];
    int pl = 0;
    int ans = 0;
    //求连续最大和
    for (int i = 1;i <= n;i++) {
        ans = max(ans, a[i] - a[pl]);
        if (a[i] <= a[pl])pl = i;
    }
    while (k--) {
        sum = (sum + ans) % M;
        ans = (ans + ans) % M;
    }
    if (sum >= 0)cout << sum % M << '\n';
    else cout << sum + M << '\n';
}

signed main()
{
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    int t;cin >> t;
    while (t--) {
        solve();
    }
    return 0;
}

C

题目大意

给定 n n n个节点的树,给定整数 k k k,要求找到最大的 x x x,使得删去 k k k条边后每块节点数量最少为 x x x

思路

找到最大值的最小,一眼二分,二分节点数量
节点最小值范围确定二分边界 [ 1 , n / k ] [1,n/k] [1,n/k] d f s dfs dfs查询判断节点数量和

ACcode

``
#include<bits/stdc++.h>

using namespace std;

#define int long long

const int M = 1e5 + 7;
vectormv[M];
int m, n, k, num;
int nex[M];

void dfs(int x, int y) {
nex[x] = 1;
for (auto p : mv[x]) {
if (p != y) {
dfs(p, x);
nex[x] += nex[p];
}
}
if (nex[x] >= m)num++, nex[x] = 0;
}

void solve()
{
cin >> n >> k;
for (int i = 0;i < M;i++)mv[i].clear();
for (int i = 2, u, v;i <= n;i++) {
cin >> u >> v;
mv[v].push_back(u);
mv[u].push_back(v);
}
int le = 1;int ri = n / k;
while (le < ri) {
m = le + ri + 1 >> 1;
num = 0;
dfs(1, 0);
if (num > k)le = m;
else ri = m - 1;
}
cout << le << ‘\n’;
}

signed main()
{
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int t;cin >> t;
while (t–) {
solve();
}
return 0;
}

  • 23
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值