Educational Codeforces Round 148 (Rated for Div. 2) ABC题

A. New Palindrome

题目描述(英文)

A. New Palindrome

A palindrome is a string that reads the same from left to right as from right to left. For example, abacaba, aaaa, abba, racecar are palindromes.

   You are given a string s
 consisting of lowercase Latin letters. The string s
 is a palindrome.

You have to check whether it is possible to rearrange the letters in it to get another palindrome (not equal to the given string s
).

Input
The first line contains a single integer t
 (1≤t≤1000
) — the number of test cases.

The only line of each test case contains a string s
 (2≤|s|≤50
) consisting of lowercase Latin letters. This string is a palindrome.

Output
For each test case, print YES if it is possible to rearrange the letters in the given string to get another palindrome. Otherwise, print NO.

You may print each letter in any case (YES, yes, Yes will all be recognized as positive answer, NO, no and nO will all be recognized as negative answer).

Example
inputCopy
3
codedoc
gg
aabaa
outputCopy
YES
NO
NO
Note
In the first test case, it is possible to rearrange the letters in the palindrome codedoc to obtain the string ocdedco, which is different from the given string, but also a palindrome.

题意

判断一个回文字符串能否交换其字母顺序,又得到一个回文字符串

思路

只要有两个不同字母的出现次数大于等于2,那么一定可以得到,否则就不行,比如:abba得到baab

代码

#include <bits/stdc++.h>
using namespace std;
int q[100];
int main(){
	string s;
	int t;
	cin>>t;
	while (t--){
		cin>>s;
		for (int i=0;i<=100;i++){
			q[i]=0;
		}
		int ans=0;
		int m=s.size();
		for (int i=0;i<m;i++){
			q[(int)s[i]-96]++;
			if (q[(int)s[i]-96]==2){
				ans++;
			}
		}
		if (ans>=2){
			cout<<"YES"<<"\n";
		}else{
			cout<<"NO"<<"\n";
		}
	}
}

注释

这段代码的功能是可以多次输入一个字符串,并判断该字符串中是否存在两个或以上重复出现的字母。如果有,则输出 YES,否则输出 NO。
具体实现如下:
首先读入一个整数t表示测试数据的组数。
循环t 次,每次读入一个字符串 s。
数组 q 相当于一个哈希表,用来记录每个字符出现的次数,数组初始化为 0。
ans 变量用来计数当前字符串中重复出现的字母个数,初值为 0。
计算字符串长度 m = s.size()。
遍历字符串s,将每个字符的出现次数在数组 q 中加1,如果某个字符的出现次数变为2,则说明当前字符串多了一个重复出现的字母,将 ans 加1。
最后根据ans是否大于等于 2 来判断输出 YES 还是 NO。
需要注意的是,代码中将字符转成 int 类型处理,从 a 到 z 的字符分别对应数字 1 到 26。因此,字母 a 对应数组 q 的下标为 1,字母 b 对应下标为 2,以此类推。

B. Maximum Sum

题目

You are given an array a1,a2,…,an
, where all elements are different.

You have to perform exactly k
operations with it. During each operation, you do exactly one of the following two actions (you choose which to do yourself):

find two minimum elements in the array, and delete them;
find the maximum element in the array, and delete it.
You have to calculate the maximum possible sum of elements in the resulting array.

Input
The first line contains one integer t
(1≤t≤104
) — the number of test cases.

Each test case consists of two lines:

the first line contains two integers n
and k
(3≤n≤2⋅105
; 1≤k≤99999
; 2k<n
) — the number of elements and operations, respectively.
the second line contains n
integers a1,a2,…,an
(1≤ai≤109
; all ai
are different) — the elements of the array.
Additional constraint on the input: the sum of n
does not exceed 2⋅105
.

Output
For each test case, print one integer — the maximum possible sum of elements in the resulting array.

Example
inputCopy
6
5 1
2 5 1 10 6
5 2
2 5 1 10 6
3 1
1 2 3
6 1
15 22 12 10 13 11
6 2
15 22 12 10 13 11
5 1
999999996 999999999 999999997 999999998 999999995
outputCopy
21
11
3
62
46
3999999986
Note
In the first testcase, applying the first operation produces the following outcome:

two minimums are 1
and 2
; removing them leaves the array as [5,10,6]
, with sum 21
;
a maximum is 10
; removing it leaves the array as [2,5,1,6]
, with sum 14
.
21
is the best answer.

In the second testcase, it’s optimal to first erase two minimums, then a maximum.

题意

有n个数字,每次选择删去一个最大的或者两个最小的,使得最后的数组和最大

思路

可以先将数组排序,然后求出其前缀和,再通过枚举每一种删去的情况,取最大值

代码

#include <bits/stdc++.h>
using namespace std;
int t,n,k;
long long a[200005],sum[200005];
int main(){
	cin>>t;
	while (t--){
		cin>>n>>k;
		sum[0]=0;
		for (int i=1;i<=n;i++){
			cin>>a[i];
		}
		sort(a+1,a+n+1);
		for (int i=1;i<=n;i++){
			sum[i]=sum[i-1]+a[i];
		}
		long long maxx=0;
		for (int i=0;i<=k;i++){
			maxx=max(maxx,sum[n-k+i]-sum[2*i]);
		}
		cout<<maxx<<endl;
	}
}

注释

这段代码的功能是读入多组数据,每组数据包括一个整数 n 和一个整数 k,以及 n 个整数,然后计算选出 k 个数所能得到的最大子序列和。
具体细节如下:
首先读入一个整数 t 表示测试数据的组数。
循环 t 次,每次读入两个整数 n 和 k。
数组 a 存储输入的 n 个整数,并按升序排序。
数组 sum 记录前缀和,即 sum[i] 表示 a[1] 到 a[i] 的和。
循环遍历 k 次,以 i 作为起点,从 sum[n-k+i] 到 sum[2*i] 就是前 k 大个中位于第一段的最大子序列和(假设第一段长度为i,则第二段长度为k-i)。
每轮遍历更新 maxx 变量到当前轮的最大子序列和。
最后输出 maxx 即可。
需要注意的是,数组的下标从 1 开始,而不是从 0 开始。另外,long long 类型的变量的范围较大,相比于 int 类型,可以更好地避免溢出问题。

C. Contrast Value

题目

For an array of integers [a1,a2,…,an]
, let’s call the value |a1−a2|+|a2−a3|+⋯+|an−1−an|
the contrast of the array. Note that the contrast of an array of size 1
is equal to 0
.

You are given an array of integers a
. Your task is to build an array of b
in such a way that all the following conditions are met:

b
is not empty, i.e there is at least one element;
b
is a subsequence of a
, i.e b
can be produced by deleting some elements from a
(maybe zero);
the contrast of b
is equal to the contrast of a
.
What is the minimum possible size of the array b
?

Input
The first line contains a single integer t
(1≤t≤104
) — the number of test cases.

The first line of each test case contains a single integer n
(1≤n≤3⋅105
) — the size of the array a
.

The second line contains n
integers a1,a2,⋅,an
(0≤ai≤109
) — elements of the array itself.

The sum of n
over all test cases doesn’t exceed 3⋅105
.

Output
For each test case, print a single integer — the minimum possible size of the array b
.

Example
inputCopy
4
5
1 3 3 3 7
2
4 2
4
1 1 1 1
7
5 4 2 1 0 0 4
outputCopy
2
2
1
3

题意

给出一个数组a,它的权值等于 |a1−a2|+|a2−a3|+⋯+|a(n−1)−an|,尝试删去a中的一些元素得到数组b,使得b的权值等于a的权值,同时让b数组尽可能的小,输出b中元素个数

思路

假如一串数组是单调的,那我们可以只留下第一个和最后一个,它的权值不变,所以我们就只用看有多少个单调队列,并将其个数+1,即可得到答案

代码

#include <bits/stdc++.h>
using namespace std;
int a[300005],b[300005];
int main(){
	int t;
	cin>>t;
	while (t--){
		int n;
		cin>>n;
		for (int i=1;i<=n;i++){
			cin>>a[i];
		}
		int cnt=1;
		for (int i=2;i<=n;i++){
			if (a[i]-a[i-1]!=0){
				b[cnt++]=a[i]-a[i-1];
			}
		}
		if (cnt==1){
			cout<<"1"<<"\n";
			continue;
		}
		int ans=0;
		int flag;
		if (b[1]>0){
			ans++;
			flag=0;
		}else{
			ans++;
			flag=1;
		}
		for (int i=2;i<cnt;i++){
			if (b[i]>0&&flag==1){
				ans++;
				flag=0;
			}else if(b[i]<0&&flag==0){
				ans++;
				flag=1;
			}
		}
		cout<<ans+1<<"\n";
	}
}

注释

这段代码的功能是读入多组数据,每组数据包括一个整数 n 和 n 个整数 a1,a2,…,an,然后统计这些数最少划分为几个连续子序列,使得每个子序列中的相邻元素差的符号是相同的。
具体实现如下:
首先读入一个整数 t 表示测试数据的组数。
循环 t 次,每次读入一个整数 n,并将接下来的 n 个整数存入数组 a 中。
根据题目要求,我们需要找到所有相邻元素差的符号是否相同的位置。因此在数组 b 中记录相邻两个数的差值,如果是 0,则不用记录。
如果数组 b 只有一个元素,则无需划分,输出 1,并进行下一轮循环。
否则,在遍历数组 b 的过程中,使用 ans 记录当前已经划分的子序列个数,flag 标记当前子序列的前一个符号是正还是负(1 为负数,0 为正数)。
遍历数组 b,如果 b[i]>0 且 flag 为 1,或者 b[i]<0 且 flag 为 0,则说明当前元素与上一个元素符号相同,应当新划分一个子序列,把 ans 加1,并更新 flag。
遍历完成后,最终答案等于 ans+1,即所有子序列个数加1。
需要注意的是,本题没有规定每个子序列必须包含至少两个元素,因此单独一个元素也可以视为一个子序列。同时,最后要记得输出换行符 “\n”。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值