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;
}
}