题意:给出n个格子,按顺序进行m种操作,每种操作能把l [ i ] 个格子涂成一种颜色。
现要求每种颜色至少出现在一个格子上,切所有格子都要涂上颜色。求每种操作开始涂的位置。
先把所有操作长度加起来,如果小于n则一定不成立。
贪心的涂格子,保证前面的操作尽可能的小且要满足涂满格子。
把每一种颜色的长度尽可能地缩小(取决与sum的大小),然后实时更新sum和pos。
当l[ i ]+pos-1>n 时,如果从pos开始涂,这种颜色的末尾格子会超过n,所以它开始涂的地方必须在pos之前。
但前面的格子都是保证的最小,所以这个操作一定会覆盖前面的格子,不成立。
#include<iostream> #include<cstring> #include<algorithm> #include<cstdio> #include<cmath> #include<map> #include<queue> #include<vector> #define ll long long #define F first #define S second #define debug(x); printf("debug%d\n",x); #define rep(f,t) for(int i=f;i<=t;i++) const int inf=0x3f3f3f3f; const int mod=1e9+7; using namespace std; const int N=1e5+5; int ans[N]; int pos; int l[N]; int n,m; ll sum; int main() { scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { scanf("%d",&l[i]); sum+=l[i]; } if(sum<n) { printf("-1\n"); return 0; } pos=1;//一种颜色开始涂的位置。 sum-=n; int flag=0; for(int i=1;i<=m;i++) { if(l[i]+pos-1>n) { flag=1; break; } if(sum>=l[i]-1) { sum-=l[i]-1; l[i]=1; } else { l[i]-=sum; sum=0; } ans[i]=pos; pos+=l[i]; } if(flag) printf("-1\n"); else { for(int i=1;i<=m;i++) { printf("%d%c",ans[i],i==m?'\n':' '); } } return 0; }