COJ 1685:贪心+set

题意:N个线段,机器最多一次录K段,不重叠的可以连续录而不占用其他资源,问最多能录几段

思路:首先经典的贪心排序方法排序(按结束时间从小到大,如果结束时间相同,按起始时间从大到小)

我们可以想象有K个机器,那我们需要记录的就是第i个机器在什么时候才会有空

对于每一段[l,r],我们只需要查找这K个机器在l时间会不会有空,如果有的话,录这一段,更新结束时间,否则抛弃这一段(后面的段只会结束时间更晚,即使结束时间相同,也将占用更多时间)

所以我们开一个set,包含k个元素,记录K个机器的工作结束时间

起始的时候都是0,所以预处理set里要插入k个0

对于每一个询问[l,r],查找有没有元素小于或等于l,如果有的话,删掉该元素, 插入r(即上面的更新)

#include"cstdio"
#include"queue"
#include"cmath"
#include"stack"
#include"iostream"
#include"algorithm"
#include"cstring"
#include"queue"
#include"map"
#include"set"
#include"vector"
#define ll long long
#define mems(a,b) memset(a,b,sizeof(a))
#define ls pos<<1
#define rs pos<<1|1
 
using namespace std;
const int MAXN = 100500;
const int MAXM = 100500;
const int INF = 0x3f3f3f3f;
 
struct node{
    int s,e;
}seg[MAXN];
int n,k;
multiset<int> x;
 
bool cmp(node a,node b){
    if(a.e==b.e) return a.s>b.s;
    return a.e<b.e;
}
 
void display(){
    multiset<int>::iterator itt;
    for(itt=x.begin();itt!=x.end();itt++) cout<<*itt<<' ';
    cout<<endl;
}
 
int main(){
    //freopen("in.txt","r",stdin);
    while(~scanf("%d%d",&n,&k)){
        for(int i=0;i<n;i++) scanf("%d%d",&seg[i].s,&seg[i].e);
        sort(seg,seg+n,cmp);
        x.clear();
        for(int i=0;i<k;i++) x.insert(0);
        multiset<int>::iterator it;
        int tot=0;
        for(int i=0;i<n;i++){
            it=x.upper_bound(seg[i].s);
            if(it!=x.begin()){
                tot++;
                it--;
                x.erase(it);
                x.insert(seg[i].e);
            }
        }
        printf("%d
",tot);
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/luxiaoming/p/5257241.html