题目描述
有一条宽度为 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 le N,S le 1000001≤N,S≤100000
0 le M < N0≤M<N
1 le w_i < N1≤wi<N
Solution:
本题较水,直接贪心。
每次能跳就跳,打好标记,并记录路径,最后就判断一下标记是否打满,未满就NO,满了就YES并按顺序输出路径经过的点。
代码:
#include<bits/stdc++.h> #define il inline #define ll long long #define For(i,a,b) for(int (i)=(a);(i)<=(b);(i)++) #define Bor(i,a,b) for(int (i)=(b);(i)>=(a);(i)--) using namespace std; const int N=100005; int n,m,s,a[N],vis[N],path[N]; il int gi(){ int a=0;char x=getchar(); while(x<'0'||x>'9')x=getchar(); while(x>='0'&&x<='9')a=(a<<3)+(a<<1)+x-48,x=getchar(); return a; } int main(){ n=gi(),m=gi(),s=gi(); For(i,1,m) a[i]=gi();a[m+1]=n; if(a[1]-a[0]<s||a[m+1]-a[m]<s) puts("NO"),exit(0); int pos=0,cnt=0; For(i,1,m+1) if(!vis[i]&&a[i]-a[pos]>=s) vis[i]=++cnt,pos=i; Bor(i,0,m) if(!vis[i]&&a[pos]-a[i]>=s) vis[i]=++cnt,pos=i; For(i,0,m+1) { if(!vis[i])puts("NO"),exit(0); path[vis[i]]=i; } puts("YES"); For(i,1,cnt) printf("%d ",path[i]); return 0; }