Codeforces 962 ABCD

比赛链接

久违的教育专场,担心hack担心了一天(无奈)

A题

题意大致是 Polycarp做了一个训练计划,给出训练的天数和每天的训练量,然后当累积训练量达到总训练量的一半或者以上的时候,Polycarp会在那一天庆祝,输出那一天是第几天。

坑点估计是总和sum/2的时候存在0.5的情况吧,这里笔者在求一半的时候先判断是不是奇数,如果是就 /2+1,不是就 /2。

#include<iostream> 
#include<string> 
#include<cstring> 
#include<vector> 
#include<map> 
#include<algorithm> 
#include<queue> 
#include<set> 
#include<cstdio> 
#include<functional> 
#include<iomanip> 
#include<cmath> 
#include<stack> 
#include<iomanip>
using namespace std;
const int maxn = 2*(int)(1e5) + 1000;
const int inf = 0x3f3f3f3f;
const int mod = 2520;
const double eps = 1e-3;
typedef long long LL;
typedef unsigned long long ull;
int a[maxn];
int main() {
	int n;
	while (~scanf("%d", &n)) {
		LL sum = 0;
		for (int i = 1; i <= n; i++) {
			scanf("%d", &a[i]);
			sum += a[i];
		}
		LL ave = sum / 2;
		if (sum & 1) ave += 1;
		int ans;
		LL cnt = 0;
		for (int i = 1; i <= n; i++) {
			cnt += a[i];
			if (cnt >= ave) {
				ans = i;
				break;
			}
		}
		printf("%d\n", ans);
	}
	return 0;
}


B题

给出一个座位的抽象字符串,.(点号)表示能坐,*表示不能坐。

现在有两个系的学生要坐座位,并且同一个系的学生不能坐在一起(也就是要隔着坐)。

问最多能坐多少个学生。

假设学生人数充足。

因为只能隔着座,当一段空着的座位是偶数个的时候,显然最大的坐法就是直接隔着坐直接填满。

如果是奇数的话,显然隔着坐一定有一个系的学生多出一个,根据贪心显然把这个位置给剩余学生多的系坐。

然后就是在上述情况时要判断学生数是否比可坐的座位数少了

(简单来说就是ifelse大法)

#include<iostream> 
#include<string> 
#include<cstring> 
#include<vector> 
#include<map> 
#include<algorithm> 
#include<queue> 
#include<set> 
#include<cstdio> 
#include<functional> 
#include<iomanip> 
#include<cmath> 
#include<stack> 
#include<iomanip>
using namespace std;
const int maxn = 2*(int)(1e5) + 1000;
const int inf = 0x3f3f3f3f;
const int mod = 2520;
const double eps = 1e-3;
typedef long long LL;
typedef unsigned long long ull;
char str[maxn];
int main() {
	int a, b;
	int n;
	while (~scanf("%d%d%d", &n, &a, &b)) {
		scanf("%s", str);
		str[n] = '*';
		str[n + 1] = '\0';
		n++;
		int cnt = 0;
		bool flag = true;
		int ans = 0;
		for (int i = 0; i <= n; i++) {
			if (a == 0 && b == 0) break;
			if (str[i] == '.') {
				cnt++;
			}
			else if (str[i] == '*') {
				if (cnt & 1) {
					int tmp1 = cnt / 2 + 1, tmp2 = cnt / 2;
					if (a > b) {
						if (a - tmp1 >= 0) {
							a = a - tmp1;
							ans += tmp1;
						}
						else {
							ans += a;
							a = 0;
						}
						if (b - tmp2 >= 0) {
							b = b - tmp2;
							ans += tmp2;
						}
						else {
							ans += b;
							b = 0;
						}
					}
					else {
						if (a - tmp2 >= 0) {
							a = a - tmp2;
							ans += tmp2;
						}
						else {
							ans += a;
							a = 0;
						}
						if (b - tmp1 >= 0) {
							b = b - tmp1;
							ans += tmp1;
						}
						else {
							ans += b;
							b = 0;
						}
					}
				}
				else {
					int tmp1 = cnt / 2;
					if (a - tmp1 >= 0) {
						a -= tmp1;
						ans += tmp1;
					}
					else {
						ans += a;
						a = 0;
					}
					if (b - tmp1 >= 0) {
						b -= tmp1;
						ans += tmp1;
					}
					else {
						ans += b;
						b = 0;
					}
				}
				cnt = 0;
			}
		}
		printf("%d\n", ans);
	}
	return 0;
}


C题

给出一个串,问最少删除多少个数字能使得剩下的数字按顺序能组成一个平方数(无前导零)


读者一定要注意前导零(笔者虽然读题时注意到了,但是写的时候就忘了,然后就wa了一发)

然后因为数据量只有1e9也就是10位数,暴力dfs枚举肯定能过 。

#include<iostream> 
#include<string> 
#include<cstring> 
#include<vector> 
#include<map> 
#include<algorithm> 
#include<queue> 
#include<set> 
#include<cstdio> 
#include<functional> 
#include<iomanip> 
#include<cmath> 
#include<stack> 
#include<iomanip>
using namespace std;
const int maxn = 2*(int)(1e5) + 1000;
const int inf = 0x3f3f3f3f;
const int mod = 2520;
const double eps = 1e-3;
typedef long long LL;
typedef unsigned long long ull;
char str[11];
int len, ans;
void dfs(int i, int del, int num) {
	if (i == len) {
		if (num == (int(sqrt(num)))*(int(sqrt(num)))&&num!=0) {
			ans = min(ans, del);
		}
		return;
	}
	int tmp = num * 10 + str[i] - '0';
	if (tmp == 0) dfs(i + 1, del + 1, tmp);
	else  dfs(i + 1, del, tmp);
	dfs(i + 1, del + 1, num);
}
int main() {
	while (~scanf("%s", str)) {
		len=strlen(str);
		ans = inf;
		dfs(0, 0, 0);
		//printf("%d\n", kk);
		if (ans == inf) printf("-1\n");
		else printf("%d\n", ans);
	}
	return 0;
}

D题

给出一串数字,现在有一种操作。

选择这串数字中的x,它在这串数字中的出现次数是>=2的,并且是同类数字中的最左边的。

现在把这样的x的最左边的拿出来,加在到第二次出现x的x上(也就是那个x*2),直到串中不存在相同的数字。(语死早)

还是看例子吧

样例

[3,4,1,2,2,1,1]  [3,4,2,2,2,1]  [3,4,4,2,1]  [3,8,2,1][3,4,1,2,2,1,1] → [3,4,2,2,2,1] → [3,4,4,2,1] → [3,8,2,1]

首先第一个出现次数>=2的数字是1,把最左边的1加到第二个1上,变成了2.以此类推

首先这道题在不断的合并过程中会产生原串中不存在的数字,也就是如果你用map的话实际开销并不是原串的个数,有可能更多。(笔者就是被坑在这里,比赛的时候re到怀疑人生)

这里首先观察这个操作的规律性,首先最后会出现哪些数字与位置无关,因为这个操作实际只与有多少个相同的数字有关。如果我们从数字最小的开始两两合并的话,最后一定能得到一个和最终结果数字相同,顺序不一定相同的串。

那么我们就可以考虑,先把最终结果算出来,然后再想办法把这个最终结果按照某些方法排序出结果。

然后就是如果弄出位置关系,显然因为操作中两个数合并之后会放在右边,那么只要建立一个结构体,每次合并的时候把右边的下表赋值给合并数就行了。

这里笔者用优先队列防止合并次数过多使得空间复杂度上升(估计会有 nlogn 的空间复杂度?)

#include<iostream> 
#include<string> 
#include<cstring> 
#include<vector> 
#include<map> 
#include<algorithm> 
#include<queue> 
#include<set> 
#include<cstdio> 
#include<functional> 
#include<iomanip> 
#include<cmath> 
#include<stack> 
#include<iomanip>
#include<functional>
using namespace std;
const int maxn = 2 * (int)(1e5) + 1000;
const int inf = 0x3f3f3f3f;
const int mod = 2520;
const double eps = 1e-3;
typedef long long LL;
typedef unsigned long long ull;
struct nodes {
	LL val;
	int index;
	nodes() {}
	nodes(LL u, int v) :val(u), index(v) {}
	bool operator <(const nodes&a)const {
		if (val == a.val) return index>a.index;
		return val > a.val;
	}
};
bool cmp(nodes a, nodes b) {
	return a.index <b.index;
}
priority_queue<nodes>que;
vector<nodes>ans;
int main() {
	int n;
	while (~scanf("%d", &n)) {
		while (!que.empty())
			que.pop();
		ans.clear();
		LL x;
		for (int i = 1; i <= n; i++) {
			scanf("%I64d", &x);
			que.push(nodes(x, i));
		}
		while (que.size() >= 2) {
			nodes g = que.top();
			que.pop();
			nodes h = que.top();
			if (g.val == h.val) {
				que.pop();
				que.push(nodes(g.val * 2, max(g.index, h.index)));
			}
			else
				ans.push_back(nodes(g.val, g.index));
		}
		ans.push_back(nodes(que.top().val, que.top().index));
		sort(ans.begin(), ans.end(), cmp);
		int len = ans.size();
		printf("%d\n", len);
		for (int i = 0; i < len; i++) {
			printf("%I64d", ans[i]);
			printf("%s", i < len - 1 ? " " : "\n");
		}
	}
	return 0;
}
其他的摸了
[3,4,1,2,2,1,1]  [3,4,2,2,2,1]  [3,4,4,2,1]  [3,8,2,1][3,4,1,2,2,1,1] → [3,4,2,2,2,1] → [3,4,4,2,1] → [3,8,2,1] .

猜你喜欢

转载自blog.csdn.net/xiuya19/article/details/79903147
今日推荐