CF 1249D1

https://codeforces.com/blog/entry/70779

分析:想到在要删去一条线段时贪心的选取右坐标最长的那一个肯定正确。

就可以利用排序,即set的自动排序再重定义运算符来处理(按左坐标的顺序插入,按右坐标大小排序),用size()表示覆盖的边数,坐标从左到右一个个该删删该增增,维护一遍。

一个技巧:vector<Node> segs[maxn]  的Node 是右坐标 和 线段的序号,而用数组下标用左坐标来表示,就能够实现上述的坐标上扫一遍的处理。

#include <bits/stdc++.h>

using namespace std;
const int maxn = 2e5+10;

struct Node{
    int r;
    int idx;
};
bool operator < (Node a,Node b){
        if(a.r != b.r)
            return a.r<b.r;
        return a.idx<b.idx;
}

vector<Node> segs[maxn];
set<int> ans;
int n,k,x,y;

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin>>n>>k;
    for(int i=0; i<n; i++){
        cin>>x>>y;
        Node temp;
        temp.r = y;
        temp.idx = i;
        segs[x].push_back(temp);
    }
    set<Node> s;
    for(int i=0; i<maxn; i++){
        while(s.size() && (*s.begin()).r<i ){
            s.erase(s.begin());
        }
        for(Node it: segs[i]){
            s.insert(it);
        }
        while(s.size() > k){
            ans.insert( (*s.rbegin()).idx );
            s.erase( *(s.rbegin()) );
        }
    }
    cout<<ans.size()<<endl;
    for(int it : ans){
        cout<<it+1<<" ";
    }
    cout<<endl; 
}


//c.begin() 返回一个迭代器,它指向容器c的第一个元素

// c.end() 返回一个迭代器,它指向容器c的最后一个元素的下一个位置

// c.rbegin() 返回一个逆序迭代器,它指向容器c的最后一个元素

// c.rend() 返回一个逆序迭代器,它指向容器c的第一个元素前面的位置
原文地址:https://www.cnblogs.com/-Zzz-/p/11787495.html