Codeforces Round #661(Div. 3)A-D

A.Remove Smallest

在这里插入图片描述

Example
input
5
3
1 2 2
4
5 5 5 5
3
1 2 4
4
1 3 4 4
1
100
output
YES
YES
NO
NO
YES
`
在这里插入图片描述

题目大意:
给你一个 n 个整数的数列,你可以每次选择满足以下条件的两个位置
(1)i ≠ j
(2)|ai−aj|≤1
并删除其中ai和aj中较小的一个问能否通过若干次操作将数列删除到只剩一个数。
思路 :
我们可以看到数据的范围很小,直接暴力枚举;记得特判。

#include<iostream>
#include<algorithm>
#include<map>
using namespace std;
map<int, int>mp;
int a[500];
int main() {
	int t;
	cin >> t;
	while (t--)
	{
		mp.clear();
		int n;
		cin >> n;
		for (int i = 1; i <= n; i++) {
			cin >> a[i];
			
		}
		sort(a + 1, a + 1 + n);
		if (n == 1) { puts("YES"); continue; }
		int flag = 0;
		for (int i = 1; i < n; i++) {
			if (a[i + 1] - a[i] > 1)
				flag = 1;
		}
		if (flag)puts("NO");
		else puts("YES");
	}
}

B.Gifts Fixing

在这里插入图片描述

Example
input
5
3
3 5 6
3 2 3
5
1 2 3 4 5
5 4 3 2 1
3
1 1 1
2 2 2
6
1 1000000000 1000000000 1000000000 1000000000 1000000000
1 1 1 1 1 1
3
10 12 8
7 5 4
output
6
16
0
4999999995
7
在这里插入图片描述
题目大意:
给定长度同为 n 的数组 a 和数组 b,每次你可以进行以下操作之一
1.对a[i]减一
2.对b[i]减一
3.对a[i],b[i]同时减一
保证所有的元素都大于0,使得最后数组a中的元素大小都相同,b中的元素大小都相同(可以不等于同一个值)求最少的操作次数。
思路:
首先找到各个数组中的最小值,因为最后数组中的元素都会等于该数组中最小的元素,题目数据范围较小,我们直接暴力枚举,当a b数组中同一位置的数均大于其对应的最小值时,我们进行操作三,否则就分别进行操作一,操作二。

#include<iostream>
#include<algorithm>
using namespace std;
int a[100], b[100];
int main() {
	int t;
	cin >> t;
	while (t--)
	{
		int n;
		cin >> n;
		int m1 = 0x3f3f3f3f, m2 = 0x3f3f3f3f;
		long long ans = 0;
		for (int i = 1; i <= n; i++)
		{
			cin >> a[i];
			m1 = min(a[i], m1);
		}
		for (int i = 1; i <= n; i++)
		{
			cin >> b[i];
			m2 = min(b[i], m2);
		}
		for (int i = 1; i <= n; i++) {
			if(a[i] > m1 && b[i] > m2) {
				int flag = min(a[i] - m1, b[i] - m2);
				ans += flag;
				a[i] -= flag;
				b[i] -= flag;
			}
			ans += b[i] - m2;
			ans += a[i] - m1;
		}
		cout << ans << endl;
	}

}

C. Boats Competition

在这里插入图片描述

Example
input
5
5
1 2 3 4 5
8
6 6 6 6 6 6 8 8
8
1 2 2 1 2 1 1 2
3
1 3 3
6
1 1 3 4 2 2
output
2
3
4
1
2

在这里插入图片描述
题目大意:
有 n 个人要参与两人一组的划船比赛,第 i 个人的质量为 wi作为比赛的组织者,你希望通过这样的方式使得比赛公平:每队的两位选手的质量和都相等。
所以你需要找到一个数,使得每对选手的质量和都等于这个数,且让参赛队队伍最多。
思路:
数据范围较小,我们直接暴力解决,首先将数据进行排序,从两端同时开始(尺取法),从最小数开始枚举,一直到最大数的二倍结束,左右开弓,记录队伍数量,得出结果。

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 100;
int a[N];
int main() {
	int t;
	cin >> t;
	while (t--)
	{
		int ans = 0, sum = 0;
		memset(a, 0, sizeof a);
		int n;
		cin >> n;
		for (int i = 1; i <= n; i++)cin >> a[i];
		sort(a + 1, a + 1 + n);
		int m1 = a[1], m2 = a[n];

		for (int i = m1; i <= m2 * 2; i++) {
			int l = 1, r = n;
			sum = 0;
			while (1) {
				while (a[l] + a[r] == i&&l<r)
					l++, r--, sum++;
				while (a[l] + a[r] > i && l < r)
					r--;
				while (a[l] + a[r] < i && l < r)
					l++;
				if (l >= r) {
					ans = max(ans, sum);
					break;
				}
			}
		}
		if (n == 1)cout << 0 << endl;
		else 
		cout << ans << endl;
	}
}

D. Binary String To Subsequences

在这里插入图片描述

Example
input
4
4
0011
6
111111
5
10101
8
01010000
output
2
1 2 2 1
6
1 2 3 4 5 6
1
1 1 1 1 1
4
1 1 1 1 1 2 3 4
对于长度为 nn,只包含 00 和 11 的一个字符串 ss,把它拆成 kk 个新字符串,使得:

题目大意:
每个新字符串是 s 的一个子序列;
s 的每一个字符在这 k 个新字符串中出现且仅出现一次;
对于每一个新字符串,相邻两个字符不同(例如 010101…,101010…)。
求出 k 的最小值。
思路:
由于是子串我在这里开了两个队列,记录上一个数字,当输入为0时即判断1的队列是否为空,如果不为空,就取出该元素在答案数组中赋值为该1的记号,否则就另开记号。

#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
const int N = 200010;
char s[N];
int a[N];
int main() {
	int t;
	cin >> t;
	while (t--)
	{
		queue<int>q0, q1;
		int n;
		cin >> n;
		cin >> s + 1;
		int flag = 0, m = 0;
		for (int i = 1; i <= n; i++) {
			if (s[i] == '0') {
				if(q1.empty())
				a[i] = ++flag;
				else {
					int t = q1.front(); q1.pop();
					a[i] = a[t];
					
				}
				q0.push(i);//记得每一次都将该元素入队
			}
			else {
				if (q0.empty())
						a[i] = ++flag;
				else {
						int t = q0.front(); q0.pop();
						a[i] = a[t];
					
					}
				q1.push(i);//记得每一次都将该元素入队
			}
		}
		cout << flag << endl;;
		for (int i = 1; i <= n - 1; i++)cout << a[i] << ' ';
		cout << a[n] << endl;
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值