Codeforces Round #715 (Div. 2) A-C题解

蒟蒻萌新第一次发文章,还请大佬们指正!

传送门

A.Average Height

题意:
有多组数据,每次给一个数组 a a a,要求重新排序,使得 a i + a i + 1 2 \frac {a_i+a_{i+1}}{2} 2ai+ai+1是整数的 i i i尽量的多,输出排序后的数组 a a a

思路:
把数组 a a a中的奇数和偶数分开,奇数放在一块,偶数放在一块,就能使满足要求的 i i i最多。

AC代码

#include <bits/stdc++.h>
using namespace std;
int a[2007];
bool cmp(int x, int y)//奇数在前,偶数在后
{
	return (x % 2 == 1 && y % 2 == 0);
}
int main()
{
	int t;
	cin >> t;
	while (t--){
		int n;
		cin >> n;
		for (int i = 1; i <= n; i++){
			cin >> a[i];
		}
		sort(a+1, a+1+n, cmp);
		for (int i = 1; i <= n; i++){
			cout << a[i] << " ";
		}
		cout << endl;
	}
	return 0;
}

B.TMT Document

题意:
有多组数据,每次给定给出一个字符串 s s s,如果能将 s s s划分成若干不相交的子序列,若每个子序列都是 T M T TMT TMT,则输出 Y E S YES YES;否则输出 N O NO NO
注:子序列的定义——如果字符串A可以通过删除几个(可能为零)字符从字符串b中获得,则字符串A是字符串b的子序列。

思路:
判断 N O NO NO的“三步走”:
1.先计算字符串中 T T T M M M的个数,若 T T T的个数不为 M M M的个数的两倍,则输出 N O NO NO
2.从头开始到最后一个 M M M的位置,若到某个位置 T T T的个数小于M的个数,则输出 N O NO NO
3.从末尾开始到第一个 M M M的位置,若到某个位置 T T T的个数小于M的个数,则输出 N O NO NO
若这三步都过了,输出 Y E S YES YES

AC代码

#include <bits/stdc++.h>
using namespace std;
int main()
{
	int t;
	cin >> t;
	while (t--){
		int n;
		string s;
		cin >> n;
		cin >> s;
		//第一步:判断T和M的个数
		int cnt1 = 0, cnt2 = 0;
		for (int i = 0; i < n; i++){
			if (s[i] == 'T'){
				cnt1++;
			}else if (s[i] == 'M'){
				cnt2++;
			}
		}
		if (cnt1 != 2*cnt2){
			cout << "NO" << endl;
			continue;
		}

        //定位第一个和最后一个M的位置
		int l = n, r = -1;
		for (int i = 0; i < n; i++){
			if (s[i] == 'M'){
				l = min(l, i);//l为第一个M的位置
				r = max(r, i);//r为最后一个M的位置
			}
		}
		
		//第二步:从头开始到最后一个M的位置,看到某个位置T的个数是否小于M的个数
		int f1 = 1;
		int t1 = 0, m1 = 0;
		for (int i = 0; i <= r; i++){
			if (s[i] == 'T'){
				t1++;
			}else if (s[i] == 'M'){
				m1++;
				if (m1 > t1){
					f1 = 0;
					break;
				}
			}
		}
		if (f1 == 0){
			cout << "NO" << endl;
			continue;
		}

		//第三步:从末尾开始到第一个M的位置,到某个位置T的个数是否小于M的个数
		int f2 = 1;
		int t2 = 0, m2 = 0;
		for (int i = n-1; i >= l; i--){
			if (s[i] == 'M'){
				m2++;
				if (m2 > t2){
					f2 = 0;
					break;
				}
			}else if (s[i] == 'T'){
				t2++; 
			}
		}
		if (f2 == 0){
			cout << "NO" << endl;
			continue;
		}
		
		//若这三步都过了,输出YES
		cout << "YES" << endl;
	}
    return 0;
}

C.The Sports Festival

题意:
给定一个数组 a a a,每次拿出来任意一个数(注意每次选的数不同),定义 d i = m a x ( a 1 + a 2 + . . . + a i ) − m i n ( a 1 + a 2 + . . . + a i ) d_i=max(a_1+a_2+...+a_i) - min(a_1+a_2+...+a_i) di=max(a1+a2+...+ai)min(a1+a2+...+ai),要求对 a a a重新排序,使得 d 1 + d 2 + . . . + d n d_1+d_2+...+d_n d1+d2+...+dn的值最小,输出最小的 d 1 + d 2 + . . . + d n d_1+d_2+...+d_n d1+d2+...+dn的值。

思路:
先对原数组 a a a进行排序,再用区间 d p dp dp。设 d p [ l ] [ r ] dp[l][r] dp[l][r]代表区间 [ l , r ] [l,r] [l,r]内的元素的最小的 d d d之和。

dp[i][j] = min(dp[i+1][j], dp[i][j-1]) + a[j] - a[i];

即“区间 [ i + 1 , j ] [i+1,j] [i+1,j]内的元素的最小的 d d d之和”与“区间 [ i , j − 1 ] [i,j-1] [i,j1]内的元素的最小的 d d d之和”两者更小的那一个,加上 a [ j ] − a [ i ] a[j]-a[i] a[j]a[i],就是区间 [ i , j ] [i,j] [i,j]内的元素的最小的 d d d之和。
最后输出 d p [ 1 ] [ n ] dp[1][n] dp[1][n]即为答案。

AC代码

#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
ll a[2007], dp[2007][2007];//三年oi一场空,不开longlong见祖宗
int main()
{
	int n;
	cin >> n;
	for (int i = 1; i <= n; i++){
		cin >> a[i];
	}
	sort(a+1, a+1+n);
	memset(dp, 0, sizeof(dp));//清零
	for (int i = n-1; i >= 1; i--){
		for(int j = i+1; j <= n; j++){
			dp[i][j] = min(dp[i+1][j], dp[i][j-1]) + a[j] - a[i];
		}
	}
	cout << dp[1][n] << endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Chosen_One_13

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值