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
Problem | Lang | Verdict | Time | Memory |
---|---|---|---|---|
C - Nastya and Strange Generator | GNU C++17 | Accepted | 46 ms | 400 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;
}