其他分享
首页 > 其他分享> > 【2022杭电多校】第三场 1009 贪心

【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