[BZOJ3396]任务调度

问题描述

有n个任务,第个任务有自己的截止时间 和惩罚 。完成一个任务需要一个单位时间。我们期望任务在截止时间 前完成,这样我们不会受到惩罚,否则我们会受到 的惩罚。你的任务是找到一个调度方案,使得受到的惩罚总和尽量小。


输入格式
第一行一个正整数n(1≤n≤3*10^5)。

接下来n行,每行包含两个正整数di(1≤di≤n), wi(1≤wi≤1000),表示第i个任务的截止时间和惩罚。


输出格式

输出文件仅一行,包含一个正整数,即最小的惩罚总和。


样例输入
7
4 7
2 6
4 5
3 4
1 3
4 2

6 1


样例输出

5


样例解释

按顺序完成2, 4, 1, 3, 7号任务,放弃5, 6号任务,可以证明这样的调度方案受到的惩罚总和最小,为5。


来源 by Quack



题解:

要使受到的惩罚小,则可以考虑将前面惩罚小的任务替换为后面惩罚大且无法按时完成的任务。

将任务按惩罚从大到小排序。运用并查集压缩路径,直接找到当前任务的可行的截止时间。


#include<cstdio>
#include<algorithm>
using namespace std;
const int N=1e5*3+10;
/*fnd[i]:记录将i时间占用的任务的截止时间
nxtE[i]:下一个截止时间为i的任务的实际结束时间*/
int n, nxtE[N], fnd[N], sum;
struct node{
	int end, w;
	bool operator < ( const node &x ) const {
		if( w!=x.w ) return w>x.w;
		return end>x.end;
	}
}tsk[N];

int main() {
	scanf( "%d", &n );
	for( int i=1; i<=n; i++ )
		scanf( "%d%d", &tsk[i].end, &tsk[i].w ), nxtE[i]=i;
	sort( tsk+1, tsk+n+1 );
	
	for( int i=1; i<=n; i++ ) {
		int e=tsk[i].end;
		while( fnd[e] ) e=nxtE[ fnd[e] ];
		if(e) nxtE[tsk[i].end]=e-1, fnd[e]=tsk[i].end;
		else sum+=tsk[i].w;
	}	
	
	printf( "%d\n", sum );
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值