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

题意:有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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值