• 博客园logo
  • 会员
  • 周边
  • 新闻
  • 博问
  • 闪存
  • 众包
  • 赞助商
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录

yumiym765

  • 博客园
  • 联系
  • 订阅
  • 管理

公告

View Post

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

posted on 2025-08-28 19:36  羊毛corn  阅读(12)  评论(0)    收藏  举报

刷新页面返回顶部
 
博客园  ©  2004-2026
浙公网安备 33010602011771号 浙ICP备2021040463号-3