Codeforces Round #634(div.3) A-E题解

A. Candies and Two Sisters
  • 将糖果分为a,b两份,且a < b,a + b = n

  • 根据题中条件分析得出糖果数n <= 2 无解

  • n为偶数 res = n / 2 - 1;奇数 res = n / 2

  • res = (n - 1)/2

	cin >> t;
	while(t--){
		cin >> n;
   		cout << (n - 1) / 2;
    }
B. Construct the String
  • 构造一个长为n,且满足所有长为a的子串中只有b个不同的字母
  • 先输出有b个不同的字母的b串,n字符串即为n // b 倍的b串
	cin >> t;
	while(t--){
		cin >> n >> a >> b;
		for(int i = 0; i < n; i++) cout << char('a' + i % b);  
		cout << endl;
	}
C. Two Teams Composing
  • 有一批学生,每个学生只拥有一个技能,现将学生分为人数相等的两组,一组中的学生只拥有同种技能,另外一组中的学生只拥有不同的技能,问每组的最大人数。

  • 最大可能的结果为总人数的一半

  • 使用book数组记录使用i技能的人数,idx记录技能的数量

  • 寻找使用相同技能最多的人数mx,结果 <= mx

  • 分情况讨论 1. n == 1,n == idx特殊情况优先讨论 2.mx 与 idx 相等时存在一个元素的交集 res = mx - 1;

mx与idx不等时,res = min(mx,idx);

#define endl '\-n'
using namespace std;
const int kN = 2 * 1e5 + 5;
int t,n,x,idx,arr[kN],mx,res;
//int book[kN];//map要比直接开数组快,但更耗内存
map<int,int> book;
int main(void){
	ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0);
	cin >> t;
	while(t--){
		idx = mx = 0;
		book.clear();
		cin >> n;
		//memset(book,0,sizeof(book));
		for(int i = 0; i < n; i++){
			cin >> x;
			if(!book[x]) book[x] = 1,arr[idx++] = x;
			else ++book[x]; 
		}
		//idx 不同技能数 寻找最大相同技能数
		for(int i = 0; i < idx; i++){
			if(book[arr[i]] > mx) mx = book[arr[i]];
		} 
		if(mx == idx) cout << mx - 1 << endl;//存在一个元素的交集
        else cout << (mx > idx ? idx : mx)<< endl;
	}
	return 0;
}
D. Anti-Sudoku
  • 每组测试样例为9x9的矩阵
  • 输出结果满足每行,每列都有两个相同的数字
  • 每一行,每一列的数字均值只出现一次,将所有的2换为1...等等
	cin >> t;
	while(t--){
		for(int i = 0; i < 9; i++){
			cin >> s;
			for(auto x : s){
				if(x == '2') cout << '1';
				else cout << x;
			}
			cout << endl;
		}
	}
E1. Three Blocks Palindrome (easy version)
  • three blocks palindrome(a,a,…,a,b,b,…,b,a,a,…,a) a,b数量可为0,前后a数量相等x个,b个
  • 输入一个序列,找到最长的合法子序列,在序列中可不连续
  • pre(i,j)为前i个数中j的个数
  • 暴力:枚举a,b
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<string>
#include<map>
#include<vector>
#define endl '\n'
using namespace std;
const int kN = 2010, kM = 30;
int t,n,ans,a[kN],pre[kN][kM];
int main(void){
	ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0);
	cin >> t;
	while(t--){
		ans = 0;
		cin >> n;
		for(int i = 1; i <= n; i++) cin >> a[i];
		for(int i = 1; i <= n; i++){//前缀和... 
			for(int j = 1; j <= 26; j++) pre[i][j] = pre[i - 1][j] + (a[i] == j);
		}
		for(int l = 1; l <= n; l++){//x从0开始枚举 
			for(int r = l; r <= n; r++){//枚举r 
				int x = 0, y = 0;
				for(int k = 1; k <= 26; k++){//l ~ r 中间范围 
					x = max(x,min(pre[l - 1][k],pre[n][k] - pre[r][k]));//左右两端k的个数可以为0 
					y = max(y,pre[r][k] - pre[l - 1][k]);//中间k的个数,可以为0	
				}
				ans = max(ans, x * 2 + y);//维护最大子序列长度 
			}
		}
		cout << ans << endl;
	}
	return 0;
}
E2. Three Blocks Palindrome (hard version)
  • 与E1相比较,有了更大的数据范围
  • 枚举左侧a的结束位置,计算b右侧结束位置
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<string>
#include<map>
#include<vector>
#define endl '\n'
using namespace std;
const int kN = 2e5 + 5, kM = 205;
int t,n,ans,a[kN],pre[kN][kM];
int main(void){
	ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0);
	cin >> t;
	while(t--){
		ans = 0;
		cin >> n;
		vector<vector<int>> at(kM); 
		for(int i = 1; i <= n; i++) cin >> a[i];
		for(int i = 1; i <= n; i++){//前缀和... 
			at[a[i]].push_back(i);//记录每个数的位置 
			for(int j = 1; j <= 200; j++){
				pre[i][j] = pre[i - 1][j] + (a[i] == j);
			}
		}
		//a所在位置,枚举l左端a的个数x,尾部倒数第x个a为r+1 
		for(int i = 1; i <= 200; i++){//枚举a 
			int sz = (int)at[i].size();
			for(int l = 0; l <= sz/2; l++){//左侧a的个数
				int r = sz - l - 1;//b区间的右侧第一个i的 
				if(l > r) break;
				else if(l == r) ans = max(ans,sz);//全a 
				else{
					int mx = 0;
					for(int j = 1; j <= 200; j++){//枚举b
						mx = max(mx,pre[at[i][r] - 1][j] - pre[at[i][l]][j]);
					}	
					ans = max(ans,2 * (l + 1) + mx);				
				} 
			}
		}
		cout << ans << endl;
	}
	return 0;
}
posted @ 2020-04-22 11:55  jimmy-cat  阅读(124)  评论(0编辑  收藏  举报