您的位置:首页 > 其它

Codeforces 853A Round#433 Div2C & Div1A Planning:优先队列或堆或排序

2017-09-07 20:14 281 查看
题意:有n(<=3e5)个飞机,第i个飞机原计划在i时刻起飞。现在机场延误,需要让这n个飞机在[ k , k+n ]时刻全部飞完,每个时刻只能飞一个飞机,同时每个飞机不能比原计划更早起飞,也就是飞机i的起飞区间应该是[ i , n+k ]。每个飞机有一个延误系数,这个飞机的延误代价=延误系数*延误时间(如果按照原计划时间起飞则延误代价=0)。求最小延误代价,以及每个飞机的起飞时刻。

题解:本题有一个很好的性质:所有飞机的延误时间为定值。证明的话……只考虑[1 , n]和[ k , k+n ]没有交集的情况(另外一种情况比较复杂),这个时候每个飞机必须延误,单个飞机延误时间=ti-i(ti是新的起飞时间),于是总的延误时间是∑(ti-i)=∑ti-∑i=(k+ k+1 + k+2 +……+k+n)-(1+2+3+……+n) = kn。那么既然总延误时间为定值,由排序不等式可以证明:延误代价最小的那个航班延误的时间越多越好,也就是起飞越靠后越好。那么我们可以直接把所有的航班放到优先队列中,从k+n向k遍历。每次取出最小代价的飞机,让它飞。这样可以保证代价小的飞机尽量晚起飞。同时注意题目的另一个条件,每个飞机不能早于原计划起飞。那么我们在某时刻,先看看这个时刻如果不在[
1 , n ]中,就按照老办法安排。如果这个时刻在[ 1, n ]中,那么我们需要先看看原计划在这个时刻起飞的飞机飞了没,如果没有就安排他飞。

Code:

#include<bits/stdc++.h>
using namespace std;
const int MAX = 3e5+100;
int n,k;
bool used[MAX];
int ans[MAX];
struct Flight{
int cost,index;
bool operator < (const Flight a)const{
return a.cost<cost;
}
Flight(int cost_=0,int index_=0):cost(cost_),index(index_){}
};
priority_queue<Flight> pq;
inline void input(){
scanf("%d%d",&n,&k);
for (int i=1;i<=n;i++){
int c;
scanf("%d",&c);
pq.push(Flight(c,i));
}
}
void solve(){
memset(used,0,sizeof used);
long long res =0;
for(int i=n+k;i>k;i--){
if (i<=n&&!used[i]){
used[i] = true;
ans[i] =i;

}else{
while (used[pq.top().index])pq.pop();
used[pq.top().index] = true;
ans[pq.top().index] = i;
res +=1LL*(i-pq.top().index)*pq.top().cost;
pq.pop();
}
}
printf("%I64d\n",res);
for (int i=1;i<=n;i++){
printf("%d ",ans[i]);
}
}
int main(){
input();
solve();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  优先队列 排序