并查集做法:
#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;
#define N 50005
long long f[N];
pair <long long ,long long > m[N]; //作为结构体的作用 第一个为first 第二个为 second 按frist排序 小到大
int find(int x){
if(x<=0) return -1; //这是边界 如果在最迟时间前都没有时间做这件事 就不再执行这个任务
if(x==f[x]) return f[x]=x-1; //并查集 实现 一个状态的(存进去就有) 位置的存放
else return find(f[x]); //如果没有找到 该点所放的位置 就接着找前面的位置
}
int main(){
long long n,sum=0;
cin>>n;
for(int i=0;i<n;i++){
f[i]=i;
cin>>m[i].second>>m[i].first;
m[i].first=-m[i].first; // 将值反过来 就变成了 从大到小的排序了 巧妙 不用定义bool判断排序了
if(m[i].second>n) m[i].second=n; //只能从n开始向下找
}
sort(m,m+n);//排序一下
f[n]=n;
for(int i=0;i<n;i++){
if(find(m[i].second)>=0) //就存入该店的最大值
sum-= m[i].first;
}
cout<<sum<<endl;
return 0;
}
贪心做法
#include<iostream>
#include<algorithm>
using namespace std;
struct act{
long long x,y;
}a[50005];
bool book[50005];
bool cmp(act a,act b){
if(a.y==b.y) return a.x<b.x; //奖励相等按时间小的排
return a.y>b.y;
}
int main(){
int n;
long long ans=0;
cin>>n;
for(int i=0;i<n;i++) cin>>a[i].x>>a[i].y;
sort(a,a+n,cmp);
//for(int i=0;i<n;i++) cout<<a[i].x<<" "<<a[i].y<<endl; //输出
for(int i=0;i<n;i++){ //在奖励优先的情况下 放任务
int k=a[i].x;
while(k){// 意思就是在k之前的几个时间里放任务
if(!book[k]){ //是否放了任务 如果没有放任务 就在时间点放下任务
book[k]=1; //放过
ans+=a[i].y; //奖励的累计
break; //该奖励已经找到地方放了
}
else k--; //该点没有找到 就放之前的地方
} //对k之前的时间段放任务
}
cout<<ans<<endl;
return 0;
}
/*
7
4 20
2 60
4 70
3 40
1 30
4 50
6 10
*/