Codeforces Round #634 (Div. 3)

A. Candies and Two Sisters

题意:两个人分n个东西,a>b,有几种分法
分析:(n-1)/2种

Code:

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <sstream>
#include <cmath>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <iomanip>
using namespace std;
#define ll long long
#define mem(a, b) memset(a,b,sizeof(a));
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define lowbit(x) (x & -x)
#define lrt nl, nr, rt << 1
#define rrt nl, nr, rt << 1 | 1
const ll Inf = 1e18;
const int inf = 0x3f3f3f3f;
template<typename T>
inline void read(T& t)
{
	t = 0;
	int f = 1;
	char ch = getchar();
	while (!isdigit(ch)) { if (ch == '-') f = -1; ch = getchar(); }
	while (isdigit(ch)) { t = t * 10 + ch - '0'; ch = getchar(); }
	t *= f;
}

int main(void)
{
	int t;
	read(t);
	while (t--) {
		int n;
		read(n);
		printf("%d\n", (n - 1) / 2);
	}
	return 0;
}

B. Construct the String

题意:构造一个长为n的字符串,使得任取一个长为a的子串,有且仅有b种字符
分析:构造一个长度为b的循环串即可

Code:

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <sstream>
#include <cmath>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <iomanip>
using namespace std;
#define ll long long
#define mem(a, b) memset(a,b,sizeof(a));
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define lowbit(x) (x & -x)
#define lrt nl, nr, rt << 1
#define rrt nl, nr, rt << 1 | 1
const ll Inf = 1e18;
const int inf = 0x3f3f3f3f;
template<typename T>
inline void read(T& t)
{
	t = 0;
	int f = 1;
	char ch = getchar();
	while (!isdigit(ch)) { if (ch == '-') f = -1; ch = getchar(); }
	while (isdigit(ch)) { t = t * 10 + ch - '0'; ch = getchar(); }
	t *= f;
}

int main(void)
{
	int t;
	read(t);
	while (t--) {
		int n, a, b;
		read(n); read(a); read(b);
		for (int i = 0; i < n; i++) printf("%c", 'a' + i % b);
		printf("\n");
	}
	return 0;
}

C. Two Teams Composing

题意:n个人有不同的技能点,分成两队,a队中每个人的技能都不同,b队所有人的技能都一样
分析:set存不同的技能数,map存拥有某种技能的人数,直接分的话,有一个人会被分到两队中,分别减去求最大值

Code:

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <sstream>
#include <cmath>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <iomanip>
using namespace std;
#define ll long long
#define mem(a, b) memset(a,b,sizeof(a));
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define lowbit(x) (x & -x)
#define lrt nl, nr, rt << 1
#define rrt nl, nr, rt << 1 | 1
const ll Inf = 1e18;
const int inf = 0x3f3f3f3f;
template<typename T>
inline void read(T& t)
{
	t = 0;
	int f = 1;
	char ch = getchar();
	while (!isdigit(ch)) { if (ch == '-') f = -1; ch = getchar(); }
	while (isdigit(ch)) { t = t * 10 + ch - '0'; ch = getchar(); }
	t *= f;
}

set<int> st;
map<int, int> mp;

int main(void)
{
	int t;
	read(t);
	while (t--) {
		st.clear();
		mp.clear();
		int n;
		read(n);
		for (int i = 1; i <= n; i++) {
			int x;
			read(x);
			st.insert(x);
			mp[x]++;
		}
		int s1 = st.size();
		int s2 = 0;
		map<int, int>::iterator it;
		for (it = mp.begin(); it != mp.end(); it++) s2 = max(s2, it->second);
		int ans = max(min(s1 - 1, s2), min(s1, s2 - 1));
		printf("%d\n", ans);
	}
	return 0;
}

D. Anti-Sudoku

题意:给出一个数独,将其转变为反数独(每行、列、宫有两个相同的)
分析:把任意一个数字改成其他的即可

Code:

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <sstream>
#include <cmath>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <iomanip>
using namespace std;
#define ll long long
#define mem(a, b) memset(a,b,sizeof(a));
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define lowbit(x) (x & -x)
#define lrt nl, nr, rt << 1
#define rrt nl, nr, rt << 1 | 1
const ll Inf = 1e18;
const int inf = 0x3f3f3f3f;
template<typename T>
inline void read(T& t)
{
	t = 0;
	int f = 1;
	char ch = getchar();
	while (!isdigit(ch)) { if (ch == '-') f = -1; ch = getchar(); }
	while (isdigit(ch)) { t = t * 10 + ch - '0'; ch = getchar(); }
	t *= f;
}

char ch[10][10];

int main(void)
{
	int t;
	read(t);
	while (t--) {
		for (int i = 1; i <= 9; i++) scanf("%s", ch[i] + 1);
		for (int i = 1; i <= 9; i++) {
			for (int j = 1; j <= 9; j++) {
				if (ch[i][j] == '1') printf("2");
				else printf("%c", ch[i][j]);
			}
			printf("\n");
		}
	}
	return 0;
}

E1. Three Blocks Palindrome (easy version)

题意:给定一个数组,从中取出一部分,都成aba这样的形式,问可以生成的最长目标数组
分析:存下每个数字的位置,因为数据范围小,可以直接枚举a和b的部分

Code:

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <sstream>
#include <cmath>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <iomanip>
using namespace std;
#define ll long long
#define mem(a, b) memset(a,b,sizeof(a));
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define lowbit(x) (x & -x)
#define lrt nl, nr, rt << 1
#define rrt nl, nr, rt << 1 | 1
const ll Inf = 1e18;
const int inf = 0x3f3f3f3f;
const int maxn = 2e3 + 5;
template<typename T>
inline void read(T& t)
{
	t = 0;
	int f = 1;
	char ch = getchar();
	while (!isdigit(ch)) { if (ch == '-') f = -1; ch = getchar(); }
	while (isdigit(ch)) { t = t * 10 + ch - '0'; ch = getchar(); }
	t *= f;
}

int an[maxn];
vector<int> p[30];

int main(void)
{
	int t;
	read(t);
	while (t--) {
		for (int i = 1; i <= 26; i++) p[i].clear() ;
		int n;
		read(n);
		for (register int i = 1; i <= n; ++i) {
			read(an[i]);
			p[an[i]].push_back(i);
		}
		int ans = 0;
		for (register int i = 1; i <= 26; ++i) {
			int cnt = p[i].size();
			ans = max(ans, cnt); //一种数字作为答案
			if (cnt <= 1) continue;
			int cnt1 = cnt / 2; //该数字放在两边的最大数量
			for (register int j = cnt1; j > 0; --j) {
				int num[30] = { 0 };
				int maxx = 0;
				for (register int k = p[i][j - 1] + 1; k < p[i][cnt - j]; ++k) num[an[k]]++;
				for (register int i = 1; i <= 26; ++i) maxx = max(maxx, num[i]);
				ans = max(ans, maxx + 2 * j);
			}
		}
		printf("%d\n", ans);
	}
	return 0;
}

E2. Three Blocks Palindrome (hard version)

题意:和E1一样,只是数据范围加大
分析:直接用E1的代码会tle,因为遍历b部分求众数时,中间部分重复遍历了,我们可以将其分成左右两个部分分别遍历,保证每个数只遍历了一遍

Code:

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <sstream>
#include <cmath>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <iomanip>
using namespace std;
#define ll long long
#define mem(a, b) memset(a,b,sizeof(a));
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define lowbit(x) (x & -x)
#define lrt nl, nr, rt << 1
#define rrt nl, nr, rt << 1 | 1
const ll Inf = 1e18;
const int inf = 0x3f3f3f3f;
const int maxn = 2e5 + 5;
template<typename T>
inline void read(T& t)
{
	t = 0;
	int f = 1;
	char ch = getchar();
	while (!isdigit(ch)) { if (ch == '-') f = -1; ch = getchar(); }
	while (isdigit(ch)) { t = t * 10 + ch - '0'; ch = getchar(); }
	t *= f;
}

int an[maxn];
vector<int> p[210];

int main(void)
{
	int t;
	read(t);
	while (t--) {
		for (int i = 1; i <= 200; ++i) p[i].clear();
		int n;
		read(n);
		for (register int i = 1; i <= n; ++i) {
			read(an[i]);
			p[an[i]].push_back(i);
		}
		int ans = 0;
		for (register int i = 1; i <= 200; ++i) {
			int cnt = p[i].size();
			ans = max(ans, cnt); //一种数字作为答案
			if (cnt <= 1) continue;
			int cnt1 = cnt / 2; //该数字放在两边的最大数量
			int num[210] = { 0 };
			int maxx = 0;
			for (int k = p[i][cnt1 - 1] + 1; k < p[i][cnt - cnt1]; ++k) num[an[k]]++;
			for (int i = 1; i <= 200; ++i) maxx = max(maxx, num[i]);
			ans = max(ans, maxx + 2 * cnt1);
			for (register int j = cnt1 - 1; j > 0; --j) {
				for (register int k = p[i][j - 1] + 1; k < p[i][j]; ++k) num[an[k]]++;
				for (register int k = p[i][cnt - j - 1]; k < p[i][cnt - j]; ++k) num[an[k]]++;
				for (register int i = 1; i <= 200; ++i) maxx = max(maxx, num[i]);
				ans = max(ans, maxx + 2 * j);
			}
		}
		printf("%d\n", ans);
	}
	return 0;
}

F咕咕咕。。。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值