题目描述
有一条宽度为 NN 的河上,小D位于坐标为 00 的河岸上,他想到达坐标为 NN 的河岸上后再回到坐标为 00 的位置。在到达坐标为 NN 的河岸之前小D只能向坐标更大的位置跳跃,在到达坐标为 NN 的河岸之后小D只能向坐标更小的位置跳跃。在河的中间有 MM 个岩石,小D希望能跳到每个岩石上恰好一次。由于小D的跳跃能力太强,小D的跳跃长度有个下限 SS ,但没有上限。现在请你判断他是否能够完成他的目标。
输入输出格式
输入格式:
第一行输入两个整数 N,M,SN,M,S ,分别表示河的宽度,岩石的数量和跳跃长度的下限。
第二行输入 MM 个整数,分别表示 MM 个岩石的坐标 w_1,w_2,\cdots,w_Nw1,w2,⋯,wN 。保证 \{w_i\}{wi} 为递增序列。
输出格式:
如果小D可以完成他的目标,第一行输出YES
,第二行输出 M+2M+2 个数,依次表示小D跳到的石头编号。特殊的,坐标为 00 的河岸编号为 00 ,坐标为 NN 的河岸标号为 M+1M+1 。如果有多种解法,允许输出任意一种。
如果小D不能完成他的目标,第一行输出NO
。
输入输出样例
输入样例#1: 复制
6 1 3 3
输出样例#1: 复制
YES 1 2 0
输入样例#2: 复制
6 2 2 2 4
输出样例#2: 复制
YES 2 3 1 0
输入样例#3: 复制
5 2 3 2 3
输出样例#3: 复制
NO
说明
1 \le N,S \le 1000001≤N,S≤100000
0 \le M < N0≤M<N
1 \le w_i < N1≤wi<N
#include "stdafx.h"
//ios::sync_with_stdio(false);
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<iostream>
#include<math.h>
#include<queue>
#include<stack>
#include<cstring>
#include<string>
using namespace std;
typedef long long LL;
int main() {
ios::sync_with_stdio(false);
int st[100010];
stack<int>way;
int n, m, s;//河的宽度 岩石的数量 跳跃下限;
scanf_s("%d%d%d", &n, &m, &s);
for (int i = 1; i <= m; i++)scanf_s("%d", &st[i]);
st[0] = 0; st[m + 1] = n;
if (st[1] < s) { printf("NO"); return 0; }
if (n - st[m] < s) { printf("NO"); return 0; }
for (int i = 3; i <= m; i++) {
if (st[i] - st[i - 2] < s) { printf("NO"); return 0; }
}//排除所有无解情况
/*每个点只扫描一次,因为每个点都要走到,所以从0到m+1的时候,满足条件的点直接输出,不满足条件的点放入栈中最后输出*/
printf("YES\n");
int on = 0, next = -1;
while (next < m + 1) {
next++;
if (st[next] - st[on] < s) {
way.push(next);
}
else {
cout << next << " ";
on = next;
}
}
while (!way.empty()) {
printf("%d ", way.top());
way.pop();
}
}