题解

BJSY_XYH 2023-11-23 18:51:18 2023-11-23 18:51:34 11 返回题目

先考虑赏金多的任务,具体什么时候做由 决定。

我们可以发现,对于每个任务,在能领取到奖金的时间范围内,能晚做就尽量晚做,这样就能给那些 较大的任务留出更多时间。

具体地,按照 排序,对于每个任务 ,完成的最晚时间为 ,找到第 天至第 天中最晚的没有被占用的一天完成任务

由于 较大,所以需要使用二分 树状数组优化。

#include<bits/stdc++.h>
using namespace std;
#define int long long
int vis[100005];
struct node{
	int A,B;
}arr[100005];
int N,M;
bool cmp(node a,node b){
	if(a.B==b.B) return a.A<b.A;
	return a.B>b.B;
}
int c[100005];
#define lowbit(x) x&(-x)

void add(int x,int v){
	while(x<=N){
		c[x]+=v;
		x+=lowbit(x);
	}
}
int sum(int x){
	int ans=0;
	while(x){
		ans+=c[x];
		x-=lowbit(x);
	}
	return ans;
}
signed main(){
	srand(time(0));
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin>>N>>M;
	for(int i=1;i<=N;i++){
		cin>>arr[i].A>>arr[i].B;
		arr[i].A=M-arr[i].A+1;
	}
	sort(arr+1,arr+1+N,cmp);
	int ans=0;
	for(int i=1;i<=N;i++){
		int q=-1;
		int l=1,r=arr[i].A;
		while(l<=r){
			int mid=(l+r)/2;
			if(sum(r)-sum(mid-1)==r-mid+1){
				r=mid-1;
			}else{
				q=mid;
				l=mid+1;
			}
		}
		if(q!=-1){
			add(q,1);
			ans+=arr[i].B;
		}
	}
	cout<<ans<<endl;
	return 0;
}

彩蛋:

我没想到正解怎么办?

简单的贪心无非就两种方案:

1.以 为第一关键字, 为第二关键字排序

2.以 为第一关键字, 为第二关键字排序

你可以两种解法分别跑一遍,对答案取

虽然这是错的,但是你可以拿到 的好成绩。

#include<bits/stdc++.h>
using namespace std;
#define int long long
struct node{
	int A,B;
}arr[100005];
int N,M;
bool cmp(node a,node b){
	if(a.B==b.B) return a.A>b.A;
	return a.B>b.B;
}
bool cmp2(node a,node b){
	if(a.A==b.A) return a.B>b.B;
	return a.A>b.A;
}
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin>>N>>M;
	for(int i=1;i<=N;i++){
		cin>>arr[i].A>>arr[i].B;
	}
	sort(arr+1,arr+1+N,cmp);
	int tm=1,ans=0;
	for(int i=1;i<=N;i++){
		if(tm+arr[i].A-1<=M){
			ans+=arr[i].B;
			tm++;
		}else{
			continue;
		}
	}
//	cout<<ans<<endl;
	sort(arr+1,arr+1+N,cmp2);
	int tm2=1,ans2=0;
	for(int i=1;i<=N;i++){
		if(tm2+arr[i].A-1<=M){
			ans2+=arr[i].B;
			tm2++;
		}else{
			continue;
		}
	}
	cout<<max(ans,ans2)<<endl;
	return 0;
}
{{ vote && vote.total.up }}