Codeforces Round 1003 (Div. 4) 补题

C1. Skibidus and Fanum Tax (easy version)

原题:C1. Skibidus and Fanum Tax (easy version)

题意:

给定一个长度为 n 的数组 a 以及长度为 m 的数组 b,对于数组 a 中的每一个数,最多可以进行一次以下操作:

  • 选择数组 b 中的一个数,将 a[i] 替换为 b[x] - a[i],即 a[i] = b[x] - a[i]

问数组 a 是否可以经过以上操作,使得数组 a 变成非递减数组,即 a0 <= a1 <= a2 <= a3 ...

  • easy 版本 m = 1.

思路:

对于每一个位置,在满足不递减的条件下,能使得 a[i] 变得更小就变得更小

  • 如果 a[i-1] <= min(num-a[i],a[i]),那么就让 a[i] 取更小的值

  • 如果 a[i-1] <= max(num-a[i],a[i]),那没办法,只能让 a[i] 取更大的值来满足条件

  • 否则就是 NO

//      https://codeforces.com/contest/2065/problem/C1

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

int t, n, m;
int a[200005];
void solve()
{
    cin >> n >> m;
    for (int i = 0; i < n; i++)
        cin >> a[i];
    int num;
    cin >> num;
    a[0] = min(num - a[0], a[0]);
    for (int i = 1; i < n; i++)
    {
        if (a[i - 1] <= min(num - a[i], a[i]))
            a[i] = min(num - a[i], a[i]);
        else if (a[i - 1] <= max(num - a[i], a[i]))
            a[i] = max(num - a[i], a[i]);
        else
        {
            cout << "NO\n";
            return;
        }
    }
    cout << "YES\n";
}

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

C2. Skibidus and Fanum Tax (hard version)

原题:C2. Skibidus and Fanum Tax (hard version)

题意:

给定一个长度为 n 的数组 a 以及长度为 m 的数组 b,对于数组 a 中的每一个数,最多可以进行一次以下操作:

  • 选择数组 b 中的一个数,将 a[i] 替换为 b[x] - a[i],即 a[i] = b[x] - a[i]

问数组 a 是否可以经过以上操作,使得数组 a 变成非递减数组,即 a0 <= a1 <= a2 <= a3 ...

思路:

数组 b 元素的选择与下标无关,那就可以排序

排序完之后二分查找第一个满足 x - a[i] >= a[i-1] 的元素 x

为什么?

  • 我们知道,a[i] 的取值要么是 a[i],要么是 数组 b 中的一个元素 num,num-a[i],即 a[i] = a[i] or (num-a[i])

对于每一个位置,在满足不递减的条件下,能使得 a[i] 变得更小就变得更小

  • 如果 a[i-1] <= min(x-a[i],a[i]),那么就让 a[i] 取更小的值
  • 如果 a[i-1] <= max(x-a[i],a[i]),那没办法,只能让 a[i] 取更大的值来满足条件
  • 否则就是 NO

为什么是找第一个满足 x - a[i] >= a[i-1] 的元素 x 呢?

  • 我们需要在满足不递减的条件下,能使得 a[i] 变得更小就变得更小

  • 如果 x 越大,那么 x-a[i] 就越大,得到的结果不会优于第一个满足条件的 x,因为我们需要尽量小的 a[i]

//      https://codeforces.com/contest/2065/problem/C2
#include <bits/stdc++.h>
using namespace std;
#define int long long

int t, n, m;
int a[200005];
void solve()
{
    cin >> n >> m;
    for (int i = 0; i < n; i++)
        cin >> a[i];
    vector<int> b(m);
    for (int i = 0; i < m; i++)
        cin >> b[i];
    sort(b.begin(), b.end());
    a[0] = min(a[0], min(b[0] - a[0], b[m - 1] - a[0]));
    for (int i = 1; i < n; i++)
    {
        int x = a[i] + a[i - 1];
        auto it = lower_bound(b.begin(), b.end(), x);
        if (it != b.end())
        {
            int mi = min(*it - a[i], a[i]), mx = max(*it - a[i], a[i]);
            if (a[i - 1] <= mi)
                a[i] = mi;
            else if (a[i - 1] <= mx)
                a[i] = mx;
            else
            {
                cout << "NO\n";
                return;
            }
        }
        else
        {
            if (a[i - 1] > a[i])
            {
                cout << "NO\n";
                return;
            }
        }
    }
    cout << "YES\n";
}

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

D. Skibidus and Sigma

原题:D. Skibidus and Sigma

题意:

给定一个 n 行 m 列矩阵,可以变换矩阵的行,问如果将这个矩阵的每个数从左往右,从上往下组成一个长度为 n * m 的数组 a,val = a[0] * (n * m) + a[1] * (n * m-1) + a[2] * (n * m-2) + ...... + a[n * m-1] * 1,那么 val 最大可以是多少?

思路:

对矩阵的每一行排序

排序规则:

  • 对比两个数组 a、b,两个数组连接起来长度为 2*m
  • 那么分别计算 a 在前、b 在前所得到的结果,结果大的放在前面
//      https://codeforces.com/contest/2065/problem/D

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

int t, n, m;
void solve()
{
    cin >> n >> m;
    vector<vector<int>> v(n, vector<int>(m));
    for (int i = 0; i < n; i++)
        for (int j = 0; j < m; j++)
            cin >> v[i][j];
    sort(v.begin(), v.end(), [](const vector<int> &a, const vector<int> &b)
         {
        int suma=0,sumb=0;
        for(int i=0;i<m;i++)suma+=a[i]*(2*m-i);
        for(int i=0;i<m;i++)suma+=b[i]*(m-i);
        for(int i=0;i<m;i++)sumb+=b[i]*(2*m-i);
        for(int i=0;i<m;i++)sumb+=a[i]*(m-i);
        return suma>sumb; });

    int ans = 0, temp = n * m;
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < m; j++)
        {
            ans += v[i][j] * temp;
            temp--;
        }
    }
    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;
}

E. Skibidus and Rizz

原题:E. Skibidus and Rizz

题意:

定义 balance_val:字符串中 '0' 的数量 x,'1' 的数量 y,balance_val = abs (x - y)。

给定 n, m, k,表示给你 n 个 '0',m 个 '1',构造长度为 n + m 的字符串,使得构造出的字符串的子串的 最大 balance_val = k;如果构造不出来,输出 -1.

思路:

  • 看 0 更多还是 1 更多,并且更多的要 >= k

假设 0 更多:

  • 先填好 k 个 0,后面再填 101010....

  • 后面只能填 1010.... 这样循环,因为一对 10 会抵消,如果后面有两个 00 连在一起,那么 balance_val 就会变大,不再是 k 了

  • 所以后面的 1 的个数一定不能比 0 的个数少,否则多出来的 0 没办法被抵消
    还有如果剩余的 1 不能超过 k,如果超过 k,balance_val 也会变大

所以:

  • 假设填好了 k 个 0 之后还剩 x 个 0, m 个 1,即 0:x 个;1:m 个

  • 有:n>=k && m >= n-k && m -(n-k) <= k

满足以上条件才能构造成功

另外 while 里面 ans += string("10") 这样会超内存
#include <bits/stdc++.h>
using namespace std;
// #define int long long

int t, n, m;
string ans;
void solve()
{
    int k;
    ans.clear();
    cin >> n >> m >> k;
    if (n >= k && n - m <= k && m <= n)
    {
        ans = string(k, '0');
        n -= k;
        while (n > 0)
            ans.append("10"), m--, n--;
        ans += string(m, '1');
        cout << ans << "\n";
    }
    else if (m >= k && m - n <= k && n <= m)
    {
        ans = string(k, '1');
        m -= k;
        while (m > 0)
            ans.append("01"), n--, m--;
        ans += string(n, '0');
        cout << ans << "\n";
    }
    else
        cout << "-1\n";
}

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

posted @   明天天晴KKK  阅读(27)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
点击右上角即可分享
微信分享提示