【2022杭电多校】第三场 1009 贪心
作者:互联网
链接
http://acm.hdu.edu.cn/showproblem.php?pid=7170
简化题意
给你n个区间,你需要往区间中填入一些点,(注意每个点最多覆盖在相同位置有交集的k个区间),使得这些点可以覆盖全部的n个区间,且点的总数最少
求点的数量的最小值
思路
贪心。
很容易想到把点填在 右端点最靠前的区间 的右端点上是最优的放法(因为不影响第一个区间的点,而且使得之后的区间存在更大的可能性被这个点覆盖)
问题是怎么处理那最多k个的区间
正解呼之欲出——
可以先找出所有的 满足“左端点<=右端点最靠前区间的右端点” 的所有区间,然后把它们按照右端点升序顺序排列
(依据的贪心准则是选取k个区间时,优先选取先结束的区间)
code
#include<bits/stdc++.h>
#define ll long long
#define pii pair<int,int>
using namespace std;
const int N = 1e5+10;
int n,k;
struct node{
int l;
int r;
}a[N];
int ql[N],qr[N];
bool vis[N];
priority_queue<pii,vector<pii>,greater<pii> >q;
inline bool cmp2(int x,int y){
if(a[x].r==a[y].r) return a[x].l<a[y].l;
return a[x].r<a[y].r;
}
inline bool cmp1(int x,int y){
return a[x].l<a[y].l;
}
int main(){
int t; cin>>t;
while(t--){
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++){
scanf("%d%d",&a[i].l,&a[i].r);
ql[i]=qr[i]=i;
vis[i]=0;
}
sort(ql+1,ql+n+1,cmp1);
sort(qr+1,qr+n+1,cmp2);
int ans=0;
for(int i=1,j=1;i<=n;i++){
if(vis[qr[i]]) continue;
while(j<=n && a[ql[j]].l<=a[qr[i]].r){
q.push(make_pair(a[ql[j]].r,ql[j]));
j++;
}
ans++;
for(int j=1;j<=k;j++){
if(q.empty()) break;
vis[q.top().second]=1;
q.pop();
}
}
printf("%d\n",ans);
}
system("pause");
return 0;
}
标签:杭电多校,端点,int,long,1009,区间,define,第三场,贪心 来源: https://www.cnblogs.com/re0acm/p/16523256.html