CDZSC_2022寒假个人训练赛21级(6)题解

  • 简单
    • C
    • E
    • F
  • 中等
    • B 博弈论、栈
    • E 贪心
  • 困难
    • A 模拟+优先队列(小根堆)
    • D dfs

A Heap Operations CodeForces - 681C

题意

有个堆,有三种操作

  • insert x — 把x加到堆里。
  • getMin x — 得到堆里的最小值,且最小值等于x,当堆为空或者最小值不等于x时操作违法。
  • removeMin — 删除堆里的最小值,当堆为空时操作违法。
    题目给出了一些操作,不一定合法,往里再添加一些操作使得所有的操作都合法,求添加操作最少的情况并按序输出全部操作(新添加的和已存在的)。

题解

优先队列模拟操作

  • 当前操作为insert x时向队列中加入x
  • 当前操作为removeMin时将队列的top()删除,若队列为空则在removeMin前先insert一个在x的定义域内的任意值就好了
  • 当前操作为getMin x时:
    • 如果队列为空,则先insert x
    • 如果队列不为空,removeMin 掉所有比x小的,在此之后若top()大于x或队列为空,则insert x

AC代码

#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<queue>
#include<cstring>
#include<ctime>
#include<string>
#include<vector>
#include<map>
#include<list>
#include<set>
#include<stack>

#include<bitset>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll> pii;
typedef pair<ll, ll> pll;
const ll N = 2e5 + 5;
const ll mod = 2017;
const ll INF = 0x3f3f3f3f;
const ll INF64 = 0x3f3f3f3f3f3f3f3f;
const double gold = (1 + sqrt(5)) / 2.0;
const double PI = acos(-1);
const double eps = 1e-8;
ll gcd(ll a, ll b) { return b == 0 ? a : gcd(b, a % b); }
ll pow(ll x, ll y, ll mod) { ll ans = 1; while (y) { if (y & 1)ans = (ans * x) % mod; x = (x * x) % mod; y >>= 1; }return ans; }
ll pow(ll x, ll y) { ll ans = 1; while (y) { if (y & 1)ans = (ans * x) % mod; x = (x * x) % mod; y >>= 1; }return ans; }
ll inv(ll x) { return pow(x, mod - 2); }

priority_queue<int,vector<int> ,greater<int> >pq;
char com[100005][10];
int s[100005];
string p;
int main() {
	int n,m;
	
	scanf("%d", &n);
	m = n;
	for (int i = 0; i < n; i++) {
		scanf("%s", com[i]);
		if (com[i][0] != 'r')
			scanf("%d", &s[i]);
	}

	for (int i = 0; i < n; i++) {
		if (com[i][0] == 'i') {
			pq.push(s[i]);
		}
		else if (com[i][0] == 'r') {
			if (pq.empty()) {
				p += "insert 0\n";
				m++;
			}
			else {
				pq.pop();
			}

		}
		else {

			while (pq.size() && pq.top() < s[i]) {
				p+="removeMin\n";
				m++;
				pq.pop();
			}
			if (pq.empty() || pq.top() != s[i]) {
				p+="insert "+to_string(s[i])+'\n';
				m++;
				pq.push(s[i]);
			}
		}
		p += com[i];
		p+=' ';
		if (com[i][0] != 'r')p += to_string(s[i]);
		p += '\n';

	}
	
	cout<< m <<'\n'<< p;
	return 0;
}

B Game with string CodeForces - 1104B

题意

题意:
两个人正在围绕着一个仅有小写字母组成的字符串 s玩一个游戏
在一个玩家的回合, 他必须选择字符串中的两个相邻并且相同字母删除。
例如, 如果当前字符串是 “xaax” 那么就只有一种可能,删除 “aa”, 所以字符串将变为 “xx”。两个人都想赢。
现在需要你求出最后谁会赢如果两人都选择最优策略。

题解

容易知道删除字符的顺序不影响总删除次数,所以实际上对于一个特定的字符串,删除次数是固定不变的,因此我们只要求出总次数然后判断奇偶性就好,判断使用栈判断,其他方法也行,栈比较方便。

AC代码

char s[100005];
char st[100005];
int main(){
	int n,k=0,ans=0;
	scanf("%s",s);
	for(int i=0;s[i];i++){
		if(k==0){
			st[k++]=s[i];
		}
		else{
			if(st[k-1]==s[i]){
				k--;
				ans++;
			}
			else {
				st[k++]=s[i];
			}
		}

	}
	printf("%s\n",ans%2?"Yes":"No");

	return 0;
}

C Splitting into digits CodeForces - 1104A

题意

将给定数拆分成多个数的组合,使种类尽量少。

题解

数据很小全部拆成1就好

AC代码

int main(){
    int n;
    scanf("%d",&n);
    printf("%d\n",n);
    for(int i = 0; i < n; i++){
        printf("1 ");
    }
    printf("\n");
    return 0;
}

D Sudoku POJ - 2676

题意

九宫格问题,也叫数独问题。把一个9行9列的网格,再细分为9个3*3的子网格,要求每行、每列、每个子网格内都只能使用一次1~9中的一个数字,即每行、每列、每个子网格内都不允许出现相同的数字。0是待填位置,其他均为已填入的数字。要求填完九宫格并输出(如果有多种结果,则只需输出其中一种)。如果给定的九宫格无法按要求填出来,则输出原来所输入的未填的九宫格。

题解

经典dfs问题,直接搜索容易超时,要一定程度的优化,使用bh[i][x]判断第i行的x有无出现过;使用bl[i][x]判断第i列的x有无出现过;使用bk[i][x]判断第i块的x有无出现过。

AC代码

#include<iostream>
#include<cstdio>
using namespace std;
int n = 0;
int f[11][11];
int bh[11][11], bl[11][11], bk[11][11];
int flag;
struct point {
	int x, y;
};
point l[82];

int judge(int x, int y) {
	for (int i = 1; i <= 3; i++)
		for (int j = 1; j <= 3; j++)
			if (x <= 3 * i&&y <= 3 * j)
				return (i - 1) * 3 + j;

}

void dfs(int num) {
	if (flag)return;
	if (num == n) {
		printf("\n");
		for (int i = 1; i <= 9; i++) {
			for (int j = 1; j <= 9; j++)
				printf("%d", f[i][j]);
			printf("\n");
		}
		flag = 1;
		return;
	}
	int x = l[num].x, y = l[num].y;
	int k = judge(l[num].x, l[num].y);
	for (int i = 1; i <= 9; i++) {
		if (!bh[x][i] && !bl[y][i])
			if (!bk[k][i]) {
				bh[x][i] = bl[y][i] = bk[k][i] = 1;
				f[x][y] = i;

				dfs(num + 1);

				bh[x][i] = bl[y][i] = bk[k][i] = 0;
				f[x][y] = 0;
			}
	}

}



int main() {
	int t;
	cin >> t;
	while (t--) {
		flag = 0;
		n = 0;
		for (int i = 1; i <= 9; i++)
			for (int j = 1; j <= 9; j++) {
				scanf("%1d", &f[i][j]);
				if (f[i][j] == 0)l[n++] = { i,j };
				else {
					bh[i][f[i][j]] = 1;
					bl[j][f[i][j]] = 1;
					bk[judge(i, j)][f[i][j]] = 1;
				}
			}
		dfs(0);
		for (int i = 0; i < 11; i++)
			for (int j = 0; j < 11; j++) {
				f[i][j] = 0;
				bl[i][j] = 0;
				bh[i][j] = 0;
				bk[i][j] = 0;
			}
		for (int i = 0; i < 82; i++) {
			l[i].x = 0;
			l[i].y = 0;
		}
	}
	return 0;
}

E 均分纸牌 计蒜客 - T2158

题意

均分纸牌

题解

经典贪心问题,求出平均数也就是最终状态,然后递推一遍算次数就好。

AC代码

int s[102];
int main() {
	int n,sum=0,ans=0;
	scanf("%d", &n);
	for (int i = 0; i < n; i++) {
		scanf("%d", s + i);
		sum += s[i];
	}
	sum /= n;
	
	for (int i = 0; i < n; i++) {
		if(i)s[i] += s[i - 1] - sum;
		ans += (s[i] - sum) ? 1 : 0;
	}
	printf("%d\n", ans);
	return 0;
}

F Space Navigation CodeForces - 1481A

题意

从给定的操作中选择一些,问你能否达到终点。

题解

统计下各种操作个数,然后比较下大小就好。

AC代码

char s[N];
 
int main() {
	int t,px,py;
	scanf("%d", &t);
	while (t--) {
		int u, d, l, r;
		u = d = l = r = 0;
		scanf("%d%d%s", &px, &py, s);
		for (int i = 0; s[i]; i++) {
			if (s[i] == 'U')u++;
			else if (s[i] == 'D')d++;
			else if (s[i] == 'L')l++;
			else if (s[i] == 'R')r++;
		}
		if (py <= u && py >= -d && px <= r && px >= -l)
			printf("YES\n");
		else printf("NO\n");
 
 
	}
	
	
	
	return 0;
}

G Mishka and Contest CodeForces - 999A

题意

给出 n 个问题的难度以及可以解决问题的能力 k,每次只能从问题列表的左边或右边解决问题,如果问题难度高于 k,其后或其前的问题就无法解决,求最多可以解决多少问题。

题解

分别从右向左、从左向右枚举,注意如果 k 大于所有问题的难度,即解决的问题数为2倍的给出问题数,直接输出问题数即可。

AC代码

nt s[105];
int main() {
	int n, k;
	scanf("%d%d",&n,&k);
	for (int i = 0; i < n; i++)
		scanf("%d", s + i);
	int ans = 0;
	for (int i = 0; i < n; i++) {
		if (s[i] > k) {
			break;
		}
		ans++;
	}
	for (int i = n-1; i>=0; i--) {
		if (s[i] > k) {
			break;
		}
		ans++;
	}
	if (ans > n)ans /= 2;
	printf("%d\n", ans);
	return 0;
}
posted @ 2022-02-08 17:10  _comet  阅读(162)  评论(0编辑  收藏  举报