Codeforces Round 1041(Div.1 + Div.2)

不愧是大名鼎鼎的 Div.1 + Div.2,这个层次的难度对我来说是很不友好的,因为我只开出来了一道题,而且还是看了很久才有思路的,B题确实对我来说有点烧脑了,但是想明白的话还是可以补一下的,下面就来看看这场有难度的比赛吧。

A. Mix Mex Max

题目链接:Problem - A - Codeforces

输入数据:

8
3
-1 -1 -1
5
1 1 1 1 0
6
5 5 1 -1 -1 1
4
-1 -1 0 -1
4
-1 1 1 -1
3
3 3 -1
5
0 0 0 0 0
7
3 0 1 4 -1 2 3

输出数据:

YES
NO
NO
NO
YES
YES
NO
NO

首先需要弄明白这几个函数的意思,max函数是这三个数中的最大值,min函数是这三个数中的最小值,mex函数是这三个数除外的第一个非负整数,要想使得mex = max - min,数组中的元素一定不能出现0,如果出现了0,那么这个0就是这三个数中的最小值,那么max - min = mex,最大值不变,剩下的mex不可能为最大值,mex一定是1-max中的一个数,如果max等于1的话那么mex就是2,所以只要数组中出现了0,就直接输出NO就行了,接下来的情况:要想使得max - min = mex,此时的数组中已经没有0了,那么任意的三个数的mex的值就一定是0了,mex = 0,即max - min = 0,也就是最大值和最小值相等了,也就是这三个数必须是同一个数,而题目中又说对于任意的三个连续的元素,都要满足这个条件,所以整个数组中的所有的元素都应该是同一个值才可以,想到这里的话这道题就迎刃而解了,我们只需要找出一个正整数,然后判断所有的数是不是与这个正整数相等就行了,如果碰到-1的话就continue(因为我们可以让-1变为这个正整数)。

代码如下:

// Problem: A. Mix Mex Max
// Contest: Codeforces - Atto Round 1 (Codeforces Round 1041, Div. 1 + Div. 2)
// URL: https://codeforces.com/contest/2127/problem/A
// Memory Limit: 256 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
using namespace std;
#define int long long 
#define endl '\n'
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
#define pii pair<int,int>
#define fi first
#define se second
const int inf = 0x3f3f3f3f;

void solve()
{
	int n;cin>>n;
	vector<int> a(n+1);
	for(int i=1;i<=n;i++) cin>>a[i];
	bool f = 1;int x = 0;
	for(int i=1;i<=n;i++)
	{
		if(a[i] > 0) x = a[i];//找出一个正整数
		if(a[i] == 0)
		{
			f = 0;//有0出现就是NO
			break;
		}
	}
	if(!f)
	{
		cout<<"NO"<<endl;
		return ;
	}
	for(int i=1;i<=n;i++)
	{
		if(a[i] == -1) continue;
		if(a[i] != x)//所有的数都必须相等且为正整数
		{
			cout<<"NO"<<endl;
			return ;
		}
	}
	cout<<"YES"<<endl;
//	cout<<fixed<<setprecision(x)<< ; 
}

signed main()// Don't forget pre_handle!
{
	IOS
	int T=1;
	cin>>T;
	while(T--) solve(); 
	return 0;
} 

B. Hamiiid, Haaamid... Hamid?

题目链接:Problem - B - Codeforces

马尼将哈米德困在一个1×n1×n的网格中。初始时,网格部分单元格是墙壁,其余为空,哈米德位于某个空格中。

每天按以下顺序发生事件:

  1. 马尼选择一个空格建造墙壁(注意他不能在哈米德当前所在位置建墙);
  2. 哈米德选择移动方向(左或右):
    • 若该方向无墙壁,他将成功逃脱;
    • 否则,他会移动到该方向最近的墙壁并摧毁它,当天结束时哈米德位于被摧毁的墙所在位置。

哈米德始终知晓所有墙壁位置。他希望最小化逃脱所需天数,而马尼则试图最大化这个天数。

你需要计算在双方都采取最优策略时,哈米德逃脱所需的天数。

输入数据:

4
3 1
..#
4 2
....
5 3
##..#
6 4
#...#.

输出数据:

1
1
3
3

对于样例三:

哈米德想最快逃生,但是马尼想让他最慢逃生,两个人都采取最佳策略,问你最少需要逃生所需的天数,很明显这是一道贪心的题目,可是在这道题的思路上是越想越混乱,最终还是得慢慢理清思路:

首先,对于哈米德来说,采取最暴力的方法就是从起点开始一直往一个方向走,对于马尼来说,他可以在哈米德行动之前就放置墙壁,所以他的最优策略肯定是让这个方向上的所有格子都变为墙壁,所以这种情况下,哈米德往左暴力走的话所需要花费的天数就是 k ,往右暴力走的话所需要花费的天数就是 n - k + 1 ,两者之间取最小值就是这种情况下的最少天数了,还有一种情况,哈米德没有必要在一个方向上走每一个格子,他只需要跳到这个方向上的第一个格子就行了,接下来在马尼的最优策略下就变成了第一种情况:走遍这个方向上剩余的所有格子,所以我们可以在遍历的时候,用 l 和 r 来记录哈米德所在位置的左边第一个墙壁以及右边的第一个墙壁,然后可以跳到这个墙壁上,所以往左走的话需要的天数就是 l + 1,往右走所需要的天数就是 n - r + 1 + 1 = n - r + 2,然后马尼要采取最佳策略,那么他就会逼着哈米德朝着那个所需天数最多的那个方向走,也就是两者取最大值,如果哈米德执意要往那个所需天数最少的方向走的话,那这时候的情况就退化为情况一了,所以这道题的代码如下:

// Problem: B. Hamiiid, Haaamid... Hamid?
// Contest: Codeforces - Atto Round 1 (Codeforces Round 1041, Div. 1 + Div. 2)
// URL: https://codeforces.com/contest/2127/problem/B
// Memory Limit: 256 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
using namespace std;
#define int long long 
#define endl '\n'
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
#define pii pair<int,int>
#define fi first
#define se second
const int inf = 0x3f3f3f3f;

void solve()
{
	int n,k;cin>>n>>k;string s;cin>>s;
	s = " " + s;int l = 0,r = inf;
	for(int i=1;i<s.size();i++)
	{
		if(i < k and s[i] == '#') l = max(l,i);//找出哈米德左端的最后一个墙壁
		if(i > k and s[i] == '#') r = min(r,i);//找出哈米德右端的第一个墙壁
	}
	int anl = l + 1;//哈米德的两个方向所需要的天数
	int anr = n - r + 1 + 1;
	//max(anl,anr)为在马尼的最优策略下哈米德所需的天数
	//min(k,n-k+1)为哈米德执意要走天数较少的方向所需的天数
	cout<<min(min(k,n-k+1),max(anl,anr))<<endl;
//	cout<<fixed<<setprecision(x)<< ; 
}

signed main()// Don't forget pre_handle!
{
	IOS
	int T=1;
	cin>>T;
	while(T--) solve(); 
	return 0;
} 

总结:

每一场的cf,都能够让我认识到我的不足,不管是在算法的应用上,还是在解题的思维和分析问题的方式与能力上,我都感觉缺乏训练,暑假训练也过去一半多了,基本该了解的一些算法也都了解过了,接下来就是不断的刷题训练强化对思维的训练和算法的应用能力的培养了,不管结果如何,每一天,每一刻的努力都是值得的,起码对我来说是充实的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值