从数据范围可以看出来是贪心
首先设t[i]为第i趟飞机的离开时间,c[i]为每延迟1分钟增加的费用
则我们需要最小化的就是sum{c[i]*(t[i]-i)}
sum{c[i]*(t[i]-i)}=sum{c[i]*t[i]}-sum{c[i]*i} 后者为常量
因此我们只需要最小化sum{c[i]*t[i]}
先上结论:最优解就是每次选取可选的航班中c[i]最大的那一个,一个大致的证明如下:
假设当前时刻是T,有两个航班i,j可选,c[i]>c[j]
若此时让j出发,则i的出发时间为T'>T,总费用即为c[j]*T+c[i]*T'<c[i]*T+c[j]*T'
因此此时让i出发最优,大致如此
为了维护当前可选的航班中最大的c[i],我们需要数据结构
priority_queue
一开始将前k个入队,之后每次将第k+i个入队,再将堆顶弹出,记录下当前的时间以及弹出的航班编号即可
最后输出答案,基本上是一道水题,不过记得要开long long,此外CF不接受%lld
代码如下:
#include <bits/stdc++.h>
#define LL long long
using namespace std;
inline LL read()
{
LL x=0;char ch=getchar();
while(ch>'9'||ch<'0')ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-'0',ch=getchar();
return x;
}
priority_queue<pair<LL,LL> > q;
LL n,k,c[300010],ans[300010];
int main()
{
n=read();
k=read();
for(LL i=1;i<=n;i++)
{
c[i]=read();
}
for(LL i=1;i<=k;i++)
{
q.push(pair<LL,LL>(c[i],i));
}
long long ret=0;
for(LL i=k+1;i<=k+n;i++)
{
if(i<=n)
{
q.push(pair<LL,LL>(c[i],i));
}
pair<LL,LL> f(q.top());
ans[f.second]=i;
ret+=f.first*(i-f.second);
q.pop();
}
cout<<ret<<endl;
for(LL i=1;i<=n;i++)
{
cout<<ans[i]<<' ';
}
cout<<endl;
return 0;
}