原题链接:A. Nastya and Strange Generator
原题截图:
题目大意:
有一个长度为n的数组s,然后要把1~n这n个整数从小到大、按照“规则”填入数组中,然后判断能否得到input中的目标数组
“规则”:
- r数组:r[i]代表此时数组s中从下标r[i]到n的第一个未填入的位置(若没有未填入的位置,则r[i]为undefined,用*表示)
- count数组:count[i]代表此时数组r中等于i的元素的个数
- 此时假设count[x]=max{count[i]},那么此时将要填入的数填入s[x](若x有多个取值,则可任意选取一个x填入s[x])
- 更新r数组和count数组
有点难以理解,举个例子就好了:
【(按照题目中的第一个输入案例target:{2,3,4,5,1}),*代表未填入】
- 【此时要填入1】
s数组:{*,*,*,*,*},r数组:{1,2,3,4,5},count数组:{1,1,1,1,1};
count数组中元素的最大值为1,此时x可在[1,5]中选取,可选取x=5,将1填入s[5] - 【此时要填入2】
s数组:{*,*,*,*,1},r数组:{1,2,3,4,*},count数组:{1,1,1,1,0};
count数组中元素的最大值为1,此时x可在[1,4]中选取,可选取x=1,将2填入s[1] - 【此时要填入3】
s数组:{2,*,*,*,1},r数组:{2,2,3,4,*},count数组:{0,2,1,1,0};
count数组中元素的最大值为2,此时x只能为2,将3填入s[2] - 【此时要填入4】
s数组:{2,3,*,*,1},r数组:{3,3,3,4,*},count数组:{0,0,3,1,0};
count数组中元素的最大值为3,此时x只能为3,将4填入s[3] - 【此时要填入5】
s数组:{2,3,4,*,1},r数组:{4,4,4,4,*},count数组:{0,0,0,4,0};
count数组汇总元素的最大值为4,此时x只能为4,将5填入s[4]
那么最终得到s数组为:{2,3,4,5,1},与target数组相同,输出“Yes”
解题思路:
那么什么样的数组是能够通过这个规则得到的呢?
再举一个抽象的例子:
【*为未填入的位置】
- 假设此时填入i得到了一个数组:{……,*,i,*,……},
i前面的位置,要填的数x,要么等于i-1,要么满足x>i
i后面的位置,要填的数y,要么等于i+1,要么满足y<i - 假设此时填入i+1得到了一个数组:{……,*,i,i+1,*,……},
i前面的位置,要填的数x,要么等于i-1,要么满足x>i+1
i+1后面的位置,要填的数y,要么等于i+2,要么满足y<i - 假设此时填入i+m得到了一个数组:{……,*,i,i+1,……,i+m,*,……}
i前面的位置,要填的数x,要么等于i-1,要么满足x>i+m
i+m后面的位置,要填的数y,要么等于i+m+1,要么满足y<i
那么只要按照这个规则,对target数组从前到后,或者从后往前遍历一遍就行了
AC代码:
#include<cstdio>
using namespace std;
const int len=1e5+10;
int t,n,key,last,p[len];
int main(){
scanf("%d",&t);
while(t--){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&p[i]);
}
key=0;
last=p[n];
for(int i=n-1;i>=1;i--){
if(p[i]==p[i+1]-1){
continue;
}
if(p[i]>last){
last=p[i];
}
else{
key=1;
break;
}
}
if(key){
printf("No\n");
}
else{
printf("Yes\n");
}
}
return 0;
}