Educational Codeforces Round 126 (Rated for Div. 2)

A. Array Balancing
题意: 交换 a i a_i ai b i b_i bi, 使得 a a a, b b b 序列相邻两项的差的绝对值最小,

分析 直接判断 a , b a,b a,b 序列相邻两项的差的绝对值之和与交换后的和,如果变小了,就交换,否则就不交换

#include<bits/stdc++.h>
#define x first
#define y seconde
#define int long long 
#define gg exit(0);
#define io ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define db printf("debug\n");
const int N = 5e5 + 10;
using namespace std;
typedef pair<int, int>PII;
int n, T;
int a[N], b[N];
void solve()
{
    cin >> n;

    for(int i = 1; i <= n ; i ++ ) cin >> a[i];

    for(int i = 1; i <= n; i ++ ) cin >> b[i];


    for(int i = 1; i <= n - 1; i ++ )  //判断就行
        if(abs(a[i] - a[i + 1]) + abs(b[i] - b[i + 1]) > abs(a[i] - b[i + 1]) + abs(b[i] - a[i + 1]))
            swap(a[i + 1],b[i + 1]);
    int res = 0;
    for(int i = 1; i <= n - 1; i ++ ) res += abs(a[i] - a[i + 1]) + abs(b[i] - b[i + 1]);

        cout << res << '\n';
}
signed main()
{
    //T = 1;
    cin >> T;
    while(T -- )
    solve();
}

B. Getting Zero

题意: 两种操作, + 1 +1 +1 × 2 ×2 ×2, 然后每次数字都要 m o d mod mod 32768 32768 32768, 求变成 0 0 0 的最小操作步数

分析: 不难想到, 我们可以先 加 X X X, 然后再成 2 Y 2^Y 2Y, 就可以 m o d mod mod 32768 32768 32768 0 0 0, 然后最优解一定在 15 15 15 以内, 因为可以直接 + 1 +1 +1, 变成偶数 然后成 2 14 2^{14} 214, 就 O K OK OK 了, 所以枚举 X ∈ [ 0 , 15 ] X ∈[0,15] X[0,15]

#include<bits/stdc++.h>
#define x first
#define y seconde
#define int long long 
#define gg exit(0);
#define io ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define db printf("debug\n");
using namespace std;
typedef pair<int, int>PII;
int n, T, pow2[110];
void solve()
{
    cin >> n;

    for(int i = 1; i <= n; i ++ )
    {
        int x, minv = 1e9;
        cin >>x;
        if(x == 0)  //特判0
          {
            cout << 0 << " ";
             continue;
         }
        for(int j = 0; j <= 15; j ++ )  //枚举
        {
            int num = x + j, res = 0;

            while(num % 2 == 0) num /= 2, res ++;
            minv = min(minv, 15 - res + j); //15 - res 是现在离2^15还差多少个2, j是前面+1的操作数
        }

        cout << minv << '\n';
    }
}
signed main()
{
    io;
    //T = 1;
    // cin >> T;
    // while(T -- )
    solve();
}

C. Water the Trees

题意: 使得所有树的高度相同, 奇数天可以给任意一棵树增加 1 1 1 的高度, 偶数天增加 2 2 2的高度, 当然也可以不增加, 求最少需要多少天

分析: 首先我们需要解决的是, 相同高度 X X X 为多少时是最优的, 我们不太清楚时, 我们先分析一下最少需要的, 首先如果一棵树达到 X X X 需要增长奇数高度时, 那么我们至少需要 1 1 1 天, 如果有 c n t cnt cnt 棵树需要增加奇数高度时, 至少需要 c n t × 2 + 1 cnt × 2 + 1 cnt×2+1 天, 因为每次增长 1 1 1 时, 是只有奇数天才能增长, 例如 有三颗树需要增长高度 1 1 1, 第一天给第一棵树增长 1 1 1, 第二天跳过, 第三天给第二棵树增长 1 1 1, 第四天跳过, 第五天给第三课树增长 1 1 1, 所以可以得出至少需要 2 × c n t − 1 2 × cnt - 1 2×cnt1 天, 所以这个时候我们可以发现, X X X 可以决定 c n t cnt cnt 的大小, 所以 X X X 取值为 { m a x ( h [ i ] ) , m a x ( h [ i ] ) + 1 max(h[i]), max(h[i]) + 1 max(h[i]),max(h[i])+1 }, 然后将奇数天和偶数天增长的高度加在一起就是 3 3 3, 需要两天, 所以总和 s u m sum sum / / / 3 × 2 3 × 2 3×2, 然后这里 s u m sum sum / / / 3 3 3 是不一定能整除, 所以判断一下余数, 如果余 1 1 1 再多加 1 1 1 就可以, 余 2 2 2 多加 2 2 2 就可以

#include<bits/stdc++.h>
#define x first
#define y seconde
#define int long long 
#define gg exit(0);
#define io ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define db printf("debug\n");
const int N = 3e5 + 10;
using namespace std;
typedef pair<int, int>PII;
int n, T;
int a[N];
void solve()
{
    cin >> n;
    int maxv = 0, ans = 1e18;
    for(int i = 1; i <= n; i ++ ) cin >> a[i], maxv = max(maxv, a[i]);


    for(int t = maxv; t <= maxv + 1; t ++ )  //枚举他们需要到达的相同高度
    {
        int sum = 0, cnt1 = 0;  //sum记录需要增长的高度, cnt1记录需要增长奇数高度的数量
        for(int i = 1; i <= n; i ++ )
        {
            int d = t - a[i];  //需要增长的高度
            sum += d;    
            if(d & 1) cnt1 ++;  //增加奇数高度
        }
        int res = 0;
        if(sum % 3 == 0)   
            res = max(sum / 3 * 2, cnt1 * 2 - 1);
        else if(sum % 3 == 1) 
        res = max(sum / 3 * 2 + 1, cnt1 * 2 - 1);
        else res = max(sum / 3 * 2 + 2, cnt1 * 2 - 1); 
        ans = min(res ,ans); //取最小
    }

    cout << ans << '\n';
}
signed main()
{
    io;
    //T = 1;
    cin >> T;
    while(T -- )
    solve();
}

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

广西小蒟蒻

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值