P10464 Task
思路
我们通过研究数据范围就可以知道:当
怎么贪心呢?
根据上面推出的结论:
bool cmp(node a,node b){
if(a.x==b.x) return a.y>b.y;
else return a.x>b.x;
}
排完序后,该怎么取求满足条件的任务呢?
看下图:这里可以暴力枚举
Code
#include<bits/stdc++.h>
#define int long long
#define N 500005
using namespace std;
multiset<int> sset;//定义集合
multiset<int>::iterator ffind;
struct node{
int x;
int y;
}a[N],b[N];
int n,m,second,cnt=0,sum=0;
bool flag=false;
bool cmp(node a,node b){//贪心策略:按 x 作为第一个关键字排序 y 作为第二关键字
if(a.x==b.x) return a.y>b.y;
else return a.x>b.x;
}
signed main(){
scanf("%lld %lld",&n,&m);
for(int i=1;i<=n;i++){
scanf("%lld %lld",&a[i].x,&a[i].y);
}
for(int i=1;i<=m;i++){
scanf("%lld %lld",&b[i].x,&b[i].y);
}
sort(a+1,a+1+n,cmp);
sort(b+1,b+1+m,cmp);
second=1;//指针初始化
for(int i=1;i<=m;i++){
for(int j=second;j<=n;j++){//从指针往后开始寻找
if(flag) break;
if(a[j].x>=b[i].x){
sset.insert(a[j].y);//合法的进入集合
if(j==n) flag=true;
}else{
second=j;
break;
}
}
ffind=sset.lower_bound(b[i].y);//在集合里面寻找第一个大于等于此时任务等级的机器人等级
if((ffind)!=(sset.end())){
cnt++;
sum+=500*b[i].x+2*b[i].y;//加上合法贡献值
sset.erase(ffind);//把这个值从集合里面删除,避免后面重复使用
}
}
printf("%lld %lld\n",cnt,sum);
return 0;
}