codeforces比赛(4):codeforces hello_2024

发布时间 2024-01-07 14:22:54作者: Tom-catlll

A、Wallet Exchange

跳转原题点击此:A题地址

1、题目大意

  经典贪心:A和B玩游戏,两人依次进行以下两个操作(注意这两个操作是依次进行,而不是选择操作!!!)是:1、交换钱包或保留钱包;2、从玩家当前钱包中取出1枚硬币(注意不能为0)。
  A先走,并且当某位玩家无法做出有效举动时,另一位玩家获胜。(即两位玩家钱包都为0)。

2、题目解析

  因为两位玩家都是选择最佳操作,所以最佳操作为将钱包里面的硬币先搞到0枚,这样就能通过交换钱包先手减去对方钱包里面的硬币。
  又因为A是先手操作,所以当钱包总数为奇数时,A为必胜态;钱包总数为偶数,B为必胜态。
  因为偶数时,两人能进行的操作为1、交换钱包减去1;2、保留钱包减去1。所以无论哪种硬币总数都减1,所以当偶数时,A最后执行只剩零枚,所以B赢;奇数同理。
  小技巧:这种简单的博弈论,直接面对案例输出即可,比如这里看案例发现a+b为偶数B赢,奇数A赢,直接输出即可。

3、具体代码

#include<bits/stdc++.h>

using namespace std;

int T;
int a, b;

void solve()
{
	cin >> a >> b;
	if((a + b) % 2 == 0)
		cout << "Bob\n";
	else
		cout << "Alice\n";
}

int main()
{
	cin >> T;
	while (T--)
	{
		solve();
	}

	return 0;
}

 

B、Plus-Minus Split

跳转原题点击此:B题地址

1、题目大意

  给定一个字符串,包含'+'和'-'两种字符,意思为+1和-1。让我们对该字符串划分为若干个依次连接的子字符串,要求划分的每个子字符串相加后的绝对值全部总和最小。

2、题目解析

  由于划分的字符串是依次连接的,所以我们划分的依据是让每个子串里面的+和-尽可能一样,所以我们只需要统计+和-的个数,然后求出其差值即可。

3、具体代码

#include<bits/stdc++.h>

using namespace std;

int T;
int n;

void solve()
{
	string s;
	int a = 0, b = 0;
	cin >> n >> s;
	for(auto t : s)
	{
		if(t == '-')
			a++;
		else
			b++;
	}
	cout << abs(a - b) << endl;
}

int main()
{
	cin >> T;
	while (T--)
	{
		solve();
	}

	return 0;
}

 

C、Grouping Increases

跳转原题点击此:C题地址

1、题目大意

  将给定的数组划分为s和t两个子数组,并且允许出现空子数组。要求划分后的s和t其最小代价之和最小。
  1、划分依据:如[3、5、2、7、1]可以划分为[3、7、1]和[5、2],只要新的子数组满足原字符串的顺序即可。
  2、代价:如[3、5、2、7、1]的代价就是2,即5>3 和 7>2。换句话说就是求出子数组中出现递增的次数

2、题目解析

  即可以生成两个栈,将元素依次存入到两个栈中;
  1、按照非递增的规律存入到符合条件地栈中,如果两个栈都满足,那就选择栈顶小的那个栈里面。这是因为保持栈的最大灵活性。如2选择放入5和3中,如果选择5,那么之后如果出现4就无法放入。所以选择较小栈顶的栈可以扩大栈的灵活性;
  2、如果两个栈都不符合条件,说明存在\(bi < b_{i+1}\),所以代价就加一。此时该元素还是放入两个栈的栈顶小的栈里面,这是因为:
  如两个栈顶元素为6、7,后面两个元素为10、7。如果10放入7后面,那么就会多一个代价,而放入6后面则不会。所以选择小的栈顶是为了更大化灵活性。

3、具体代码

#include<bits/stdc++.h>

using namespace std;

const int N = 2e5+10;
const int INF = 1e9 + 10;

int T;
int n;
int f[N];

void solve()
{
	cin >> n;
	int ans = 0;
	for(int i = 1; i <= n; i++)
		cin >> f[i];
		
	stack<int> a, b;
	a.push(INF), b.push(INF);	// 初始化
	for(int i = 1; i <= n; i++)
	{
		int x = a.top();
		int y = b.top();
		// 分类讨论,将当前数存放到t还是s中
		// 1、当该数都比t和s的栈顶<=
		if(f[i] <= x && f[i] <= y)
		{
			// 放入进行栈顶小的那个栈里面
			if(x < y)
				a.push(f[i]);
			else
				b.push(f[i]);
		}
		// 2、如果a栈小,放入a
		else if(f[i] <= x && f[i] > y)
			a.push(f[i]);
		// 3、如果b栈小,放入b
		else if(f[i] > x && f[i] <= y)
			b.push(f[i]);
		// 4、如果都比两个栈顶大
		else if(f[i] > x && f[i] > y)
		{
			// 放入栈顶小的那个栈中
			if(x > y)
				b.push(f[i]);
			else
				a.push(f[i]);
			// 由于出现了递增,那么答案代价就加一
			ans++;
		}
	}
	cout << ans << endl;
}

int main()
{
	cin >> T;
	while (T--)
	{
		solve();
	}

	return 0;
}

 

未完待续

  后序题目对我来说实在是太难了,得等很久很久才能补掉。