【Codeforces 1340A】Nastya and Strange Generator(思维)

探讨了如何通过特定规则填充数组,以匹配目标数组,分析了数组填充过程中的数值分布规律,提供了一种判断是否能按规则生成目标数组的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原题链接:A. Nastya and Strange Generator
原题截图:
Nastya and Strange Generator(1)Nastya and Strange Generator(2)
题目大意:
有一个长度为n的数组s,然后要把1~n这n个整数从小到大、按照“规则”填入数组中,然后判断能否得到input中的目标数组

“规则”:

  1. r数组:r[i]代表此时数组s中从下标r[i]到n的第一个未填入的位置(若没有未填入的位置,则r[i]为undefined,用*表示)
  2. count数组:count[i]代表此时数组r中等于i的元素的个数
  3. 此时假设count[x]=max{count[i]},那么此时将要填入的数填入s[x](若x有多个取值,则可任意选取一个x填入s[x])
  4. 更新r数组和count数组

有点难以理解,举个例子就好了:
【(按照题目中的第一个输入案例target:{2,3,4,5,1}),*代表未填入】

  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. 【此时要填入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. 【此时要填入3】
    s数组:{2,*,*,*,1},r数组:{2,2,3,4,*},count数组:{0,2,1,1,0};
    count数组中元素的最大值为2,此时x只能为2,将3填入s[2]
  4. 【此时要填入4】
    s数组:{2,3,*,*,1},r数组:{3,3,3,4,*},count数组:{0,0,3,1,0};
    count数组中元素的最大值为3,此时x只能为3,将4填入s[3]
  5. 【此时要填入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”


解题思路:
那么什么样的数组是能够通过这个规则得到的呢?
再举一个抽象的例子:
【*为未填入的位置】

  1. 假设此时填入i得到了一个数组:{……,*,i,*,……},
    i前面的位置,要填的数x,要么等于i-1,要么满足x>i
    i后面的位置,要填的数y,要么等于i+1,要么满足y<i
  2. 假设此时填入i+1得到了一个数组:{……,*,i,i+1,*,……},
    i前面的位置,要填的数x,要么等于i-1,要么满足x>i+1
    i+1后面的位置,要填的数y,要么等于i+2,要么满足y<i
  3. 假设此时填入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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值