2025/08/27 训练
一些跟数组操作有关的题目
遇到这种题总是没啥思路,找几道题学习一下。
rating : 1200 ~ 1600
<------------------>
C. Chamo and Mocha's Array
链接
\(\hspace{20px}\)假设最终答案为 \(x\),不难证明我们只需要至多一次操作就可以使得一个长度至少为 \(2\) 的子数组的所有元素都变成 \(x\),那么一定存在一个长度为 \(3\) 且中位数为 \(y\)(\(y \ge x\)) 的子数组。
\(\hspace{20px}\)如果 \(n = 2\),则答案是最小的元素。
\(\hspace{20px}\)如果 \(n \ge 3\),我们遍历所有长度为 \(3\) 的子数组,答案是所有长度为 \(3\) 的子数组的中位数的最大值。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
void solve(){
int n;
cin >> n;
vector<int> a(n);
for(int i = 0;i < n;i++){
cin >> a[i];
}
int ans = 0;
if(n == 2){
ans = min(a[0], a[1]);
}else{
for(int i = 0;i < n - 2;i++){
vector<int> tmp;
for(int j = 0;j < 3;j++){
tmp.push_back(a[i + j]);
}
sort(tmp.begin(), tmp.end());
ans = max(ans, tmp[1]);
}
}
cout << ans << "\n";
}
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr); cout.tie(nullptr);
int T = 1;
cin >> T;
while(T--){
solve();
}
return 0;
}
B. Add 0 or K
\(\hspace{20px}\)给你一个由 \(n\) 个正整数 \(a_1, a_2, \ldots, a_n\) 和一个正整数 \(k\) 组成的数组。
\(\hspace{20px}\)在一次操作中,你可以选择多个下标 \(i\),将 \(0\) 或 \(k\) 添加到这些 \(a_i\) 中。
\(\hspace{20px}\)你的任务是执行最多 \(k\) 次这样的操作,使 \(\gcd(a_1, a_2, \dots, a_n) > 1\) 成立。可以证明这总是可能的。
\(\hspace{20px}\)输出运算后的最终数组。您不必输出操作本身。
有多种构造方法:
第一种:\(a_i \gets a_i + k \cdot (a_i \bmod (k+1))\)
容易得出操作次数为 \(a_i \bmod (k+1)\) 次。
点击查看代码
void solve(){
int n;
long long k;
cin >> n >> k;
vector<long long> a(n);
for(int i = 0;i < n;i++){
cin >> a[i];
}
if(n == 1){
cout << a[0] + k << "\n";
return;
}
for(int i = 0;i < n;i++){
long long less = a[i] % (k + 1);
if(less != 0){
a[i] += less * k;
}
}
for(int i = 0;i < n;i++){
cout << a[i] << " ";
}
cout << "\n";
}
第二种:找出一个小质数 \(p\),并使所有元素都能被 \(p\) 整除。
点击查看代码
void solve(){
int n, k;
cin >> n >> k;
vector<long long> a(n);
for (auto &i : a) {
cin >> i;
}
for (int g = 2;; g++) {
if (gcd(g, k) != 1)
continue;
for (auto &i : a) {
while (i % g != 0)
i += k;
}
for (auto i : a)
cout << i << ' ';
cout << '\n';
break;
}
}
B. Array Craft
对于大小为 \(m\) 的数组 \(b\) ,我们可以这样定义:
- \(b\) 的最大前缀位置是满足 \(b_1+\ldots+b_i=\max_{j=1}^{m}(b_1+\ldots+b_j)\) 的最小索引 \(i\) ;
- \(b\) 的最大后缀位置是满足 \(b_i+\ldots+b_m=\max_{j=1}^{m}(b_j+\ldots+b_m)\) 的最大索引 \(i\) 。
给你三个整数 \(n\) 、 \(x\) 和 \(y\) 。( \(x > y\) ).请构造一个大小为 \(n\) 的数组 \(a\) 满足以下条件:
- 对于所有 \(1 \le i \le n\) 而言, \(a_i\) 要么是 \(1\) 要么是 \(-1\) ;
- \(a\) 的最大前缀位置是 \(x\) ;
- \(a\) 的最大后缀位置是 \(y\) 。
如果有多个数组满足条件,则打印任意一个。可以证明,在给定的条件下,这样的数组总是存在的。
构造思路:
注意到 \(y < x\),那么从 \(y\) 到 \(x\) 全赋值为 \(1\),然后向两边以 "\(-1~1 ~-1 ~1\)" 的方式构造。
点击查看代码
void solve(){
int n, x, y;
cin >> n >> x >> y;
vector<int> a(n + 1);
for(int i = y;i <= x;i++){
a[i] = 1;
}
int base = -1;
for(int i = x + 1;i <= n;i++){
a[i] = base;
base = base == -1 ? 1 : -1;
}
base = -1;
for(int i = y - 1;i >= 1;i--){
a[i] = base;
base = base == -1 ? 1 : -1;
}
for(int i = 1;i <= n;i++){
cout << a[i] << " ";
}
cout << "\n";
}
bonus:\(x \le y\) 应如何解决。
暂时还没有想法,留到后面填坑吧qwq
浙公网安备 33010602011771号