[codeforces 1341C] Nastya and Strange Generator 让人郁闷的题

Codeforces Round #637 (Div. 2) - Thanks, Ivan Belonogov!   比赛人数15390

[codeforces 1341C]   Nastya and Strange Generator   让人郁闷的题

总目录详见https://blog.csdn.net/mrcrack/article/details/103564004

在线测评地址http://codeforces.com/contest/1341/problem/C

ProblemLangVerdictTimeMemory
C - Nastya and Strange Generator GNU C++17Accepted46 ms400 KB

原以为是非英文母语看不懂,看了评论,才发现,英文母语也看不懂,可见题意啊。

明明题中正文讲解的例子,就是样例中第一组数据的处理过程的片段,出题人,尽然没让读题人看出。

题中正文讲解的例子,r=[3,3,3,4,×]来的莫名其妙,怎么得出的?

该题杀伤力太大了,看不懂题,让笔者郁闷了一天(从比赛结束到此文章发表)。

该题有三个数组,排列数数组p,r数组,count数组,三者间互相影响变化

题意最难懂的地方,r数组数值是如何变化的。

For all j from 1 to n, we calculate rj  — the minimum index such that j≤rj≤n, and the position rj is not yet occupied in the permutation. If there are no such positions, then we assume that the value of rj is not defined.

要清晰的理解上面这句英文,请看下面的模拟过程。

r数组,r[i]表示p[i]自身及右边第一个为空的位置(这个位置指的是p数组中的位置)

样例算法过程如下

讲一组输出为Yes的样例

5
2 3 4 5 1
Yes

0.初始
p数组位置1 2 3 4 5
p数组数值0 0 0 0 0

r数组,r[i]表示p[i]自身及右边第一个为空的位置
r数组位置1 2 3 4 5
r数组数值1 2 3 4 5


count数组位置1 2 3 4 5
count数组数值1 1 1 1 1

1.第一步,寻找数值1放入p数组中的位置
因count数值全是1,随机选一个位置5
请注意5对应p数组的位置5,需将数值1放入p数组中的位置5,表示p[5]=1

三个数组最新值如下
p数组位置1 2 3 4 5
p数组数值0 0 0 0 1  请注意,数值1已经放入位置5

r数组,r[i]表示p[i]自身及右边第一个为空的位置
r数组位置1 2 3 4 5
r数组数值1 2 3 4 ×  请注意,p数组中,数值1已经放入位置5, 故位置5已被占用,
并且已达到p数组的位置右边界,故r[5]待定,由×表示

count数组位置1 2 3 4 5
count数组数值1 1 1 1 0

2.第二步,寻找数值2放入p数组中的位置
因count数值有4个1,随机选一个位置1
请注意1对应p数组的位置1,需将数值2放入p数组中的位置1,表示p[1]=2

三个数组最新值如下
p数组位置1 2 3 4 5
p数组数值2 0 0 0 1  请注意,数值2已经放入位置1

r数组,r[i]表示p[i]自身及右边第一个为空的位置
r数组位置1 2 3 4 5
r数组数值2 2 3 4 ×  请注意,p数组中,数值2已经放入位置1, 故位置1已被占用,
故r[1]=2

count数组位置1 2 3 4 5
count数组数值0 2 1 1 0

3.第三步,寻找数值3放入p数组中的位置
因count数值最大为2,对应位置2
请注意2对应p数组的位置2,需将数值3放入p数组中的位置2,表示p[2]=3

三个数组最新值如下
p数组位置1 2 3 4 5
p数组数值2 3 0 0 1  请注意,数值3已经放入位置2

r数组,r[i]表示p[i]自身及右边第一个为空的位置
r数组位置1 2 3 4 5
r数组数值3 3 3 4 ×  请注意,p数组中,数值3已经放入位置2, 故位置2已被占用,
故r[2]=3,r[1]=r[2]=3

count数组位置1 2 3 4 5
count数组数值0 0 3 1 0

4.第四步,寻找数值4放入p数组中的位置
因count数值最大为3,对应位置3
请注意3对应p数组的位置3,需将数值4放入p数组中的位置3,表示p[3]=4

三个数组最新值如下
p数组位置1 2 3 4 5
p数组数值2 3 4 0 1  请注意,数值4已经放入位置3

r数组,r[i]表示p[i]自身及右边第一个为空的位置
r数组位置1 2 3 4 5
r数组数值4 4 4 4 ×  请注意,p数组中,数值4已经放入位置3, 故位置3已被占用,
故r[3]=4,r[2]=r[3]=4,r[1]=r[2]=4

count数组位置1 2 3 4 5
count数组数值0 0 0 4 0

5.第五步,寻找数值5放入p数组中的位置
因count数值最大为4,对应位置4
请注意4对应p数组的位置4,需将数值5放入p数组中的位置4,表示p[4]=5

三个数组最新值如下
p数组位置1 2 3 4 5
p数组数值2 3 4 5 1  请注意,数值5已经放入位置4

r数组,r[i]表示p[i]自身及右边第一个为空的位置
r数组位置1 2 3 4 5
r数组数值× × × × ×  请注意,p数组中,数值5已经放入位置4, 故位置4已被占用,
故r[4]=r[5]=×,r[3]=r[4]=×,r[2]=r[3]=×,r[1]=r[2]=×

count数组位置1 2 3 4 5
count数组数值0 0 0 0 0

6.至此
p数组位置1 2 3 4 5
p数组数值2 3 4 5 1

完全对应输入数据
5
2 3 4 5 1

故输出Yes

讲一组输出为No的样例

3
1 3 2
No

0.初始
p数组位置1 2 3
p数组数值0 0 0

r数组,r[i]表示p[i]自身及右边第一个为空的位置
r数组位置1 2 3
r数组数值1 2 3


count数组位置1 2 3 4 5
count数组数值1 1 1 1 1

1.第一步,寻找数值1放入p数组中的位置
因count数值全是1,随机选一个位置1
请注意1对应p数组的位置1,需将数值1放入p数组中的位置1,表示p[1]=1

三个数组最新值如下
p数组位置1 2 3
p数组数值1 0 0  请注意,数值1已经放入位置1

r数组,r[i]表示p[i]自身及右边第一个为空的位置
r数组位置1 2 3
r数组数值2 2 3  请注意,p数组中,数值1已经放入位置1, 故位置1已被占用,
故r[1]=2
count数组位置1 2 3
count数组数值0 2 1

2.第二步,寻找数值2放入p数组中的位置
因count数值最大为2,对应位置2
请注意2对应p数组的位置2,需将数值2放入p数组中的位置2,表示p[2]=2

三个数组最新值如下
p数组位置1 2 3
p数组数值1 2 0  请注意,数值2已经放入位置2

r数组,r[i]表示p[i]自身及右边第一个为空的位置
r数组位置1 2 3
r数组数值3 3 3  请注意,p数组中,数值2已经放入位置2, 故位置2已被占用,
故r[2]=3,r[1]=r[2]=3

count数组位置1 2 3
count数组数值0 0 3

3.第三步,寻找数值3放入p数组中的位置
因count数值最大为3,对应位置3
请注意3对应p数组的位置3,需将数值3放入p数组中的位置3,表示p[3]=3

三个数组最新值如下
p数组位置1 2 3
p数组数值1 2 3  请注意,数值3已经放入位置3

r数组,r[i]表示p[i]自身及右边第一个为空的位置
r数组位置1 2 3
r数组数值× × ×  请注意,p数组中,数值3已经放入位置3, 故位置3已被占用,
并且已达到p数组的位置右边界,故r[3]待定,由×表示,故r[2]=r[3]=×,r[1]=r[2]=×

count数组位置1 2 3
count数组数值0 0 0

4.至此
p数组位置1 2 3
p数组数值1 2 3

不对应输入数据
3
1 3 2

故输出No

多算几组数据,我们可以发现规律,输出Yes情况的p数组

p[i+1]要么比p[i]小,要么=p[i]+1。

也即所有的数据,p[i+1]-p[i]<=1,则输出Yes

也即出现一组数据p[i+1]-p[i]>=2,则输出No

AC代码如下

#include <stdio.h>
#define maxn 100010
int p[maxn];
int main(){
	int t,n,i,flag;
	scanf("%d",&t);
	while(t--){
		scanf("%d",&n);
		flag=0;
		for(i=1;i<=n;i++)scanf("%d",&p[i]);
		p[0]=p[1];//边界处理,保证p[1]-p[0]==0
		for(i=1;i<=n;i++)
			if(p[i]-p[i-1]>=2){
				flag=1;
				break;
			}
		if(flag)printf("No\n");
		else printf("Yes\n");
	}
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值