Educational Codeforces Round 126 (Rated for Div. 2) A - C

A. Array Balancing

题意:给定一个操作,可以交换 a i ai ai b i bi bi 使得两序列相邻绝对值的和最小

做法:小的放上面,大的放下面

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

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int t;
    cin >> t;
    while (t--)
    {
        int n, m;
        cin >> n;
        vector<int> a(n), b(n);
        for (int i = 0; i < n; i++) cin >> a[i];
        for (int i = 0; i < n; i++) cin >> b[i];
        for (int i = 0; i < n; i++) if (a[i] > b[i]) swap(a[i], b[i]);
        int ans = 0;
        for (int i = 0; i < n - 1; i++) ans += abs(a[i] - a[i + 1]);
        for (int i = 0; i < n - 1; i++) ans += abs(b[i] - b[i + 1]);
        cout << ans << '\n';
    }
    return 0;
}

B. Getting Zero

题意:给你两个操作和 n n n 个数,问你将第 i i i 个数变成 0 0 0 的最少操作次数

做法:可以考虑记忆化搜索预处理出来所有答案然后输出,也可以BFS直接干

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int mod = 32768;
bool st[40000];

int bfs(int x)
{
    memset(st, false, sizeof st);
    queue<pair<int, int>> q;
    q.push({x, 0});
    st[x] = true;
    while (q.size())
    {
        auto t = q.front();
        q.pop();
        int x = t.first;
        int y = t.second;
        if (x == 0) return y;
        if (!st[(x + 1) % mod])
        {
            st[(x + 1) % mod] = true;
            q.push({(x + 1) % mod, y + 1});
        }
        if (!st[(x * 2) % mod])
        {
            st[(x * 2) % mod] = true;
            q.push({(x * 2) % mod, y + 1});
        }
    }
}

signed main()
{
    int n;
    cin >> n;
    map<int, int> mp;
    for (int i = 0; i < n; i++)
    {
        int x;
        cin >> x;
        // 如果没搜过就搜,搜过了直接输出答案
        if (!mp.count(x)) mp[x] = bfs(x);
        cout << mp[x] << " ";
    }
    return 0;
}

C. Water the Trees

题意:奇数天浇水长1,偶数天浇水长2,问多少天可以让所有树都一样高

做法:二分答案,注意最终的高度只可能是最初所有树高度的 m a x max max m a x + 1 max + 1 max+1

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

signed main()
{
    int t;
    cin >> t;
    while (t--)
    {
        int n;
        cin >> n;
        vector<int> a(n);
        for (int i = 0; i < n; i++) cin >> a[i];
        int maxx = *max_element(a.begin(), a.end());
        int ans = 1e18;
        for (int mx : {maxx, maxx + 1})
        {
            int num1 = 0, sum = 0;
            for (int i = 0; i < n; i++)
            {
                if ((mx - a[i]) % 2) num1++;
                sum += mx - a[i];
            }
            int l = 0, r = 1e18;
            while (l < r)
            {
                int mid = l + r >> 1;
                int cnt2 = mid / 2, cnt1 = mid - mid / 2;
                if (cnt1 >= num1 && cnt1 + cnt2 * 2 >= sum) r = mid;
                else l = mid + 1;
            }
            ans = min(l, ans);
        }
        cout << ans << '\n';
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值