二分一个最大的位置$x$,计算$t=\sum_{i=1}^k\lfloor\frac{x}{a_i}\rfloor$。
如果$t\leq n$,那么说明就算全部检票员都走到了这里,也不够$n$个指令,所以可以先将所有检票员尽量向$x$位置走,并将用掉的指令数扣除。
然后将$x$适当往前调整,使得每个检票员还差至少一步。
因为$a_i$互不相同,并且$a_i\leq 100000$,所以剩余指令数并不多,用堆直接模拟即可。
时间复杂度$O(k\log^2k)$。
#include<cstdio>
#include<algorithm>
#include<queue>
#define N 100010
using namespace std;
typedef long long ll;
typedef pair<ll,int> P;
int n,i,a[N];ll m,L,R,mid,fin,now,ans[N];priority_queue<P,vector<P>,greater<P> >Q;
inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';}
bool check(ll x){
ll t=m;
for(int i=1;i<=n;i++){
t-=x/a[i];
if(t<0)return 0;
}
return 1;
}
int main(){
scanf("%lld",&m);read(n);
for(i=1;i<=n;i++){
read(a[i]);
if(a[i]>R)R=a[i];
}
L=R+1,R*=m;
while(L<=R)if(check(mid=(L+R)>>1))L=(fin=mid)+1;else R=mid-1;
for(R=fin,i=1;i<=n;i++)R=min(R,max((fin/a[i]-1)*a[i],0LL));
for(i=1;i<=n;i++)now+=R/a[i],Q.push(P(R/a[i]*a[i],i));
while(now<m){
P t=Q.top();Q.pop();
ans[t.second]=++now;
t.first+=a[t.second];
Q.push(t);
}
for(i=1;i<n;i++)printf("%lld ",ans[i]);printf("%lld",ans[n]);
return 0;
}