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
题意:
给定一个 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
题意:
定义 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;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现