正着想很难,但是反着想就容易有思路
/*
将问题转化为 挑选最多的线段,每个点的覆盖次数不超过k次
multiset里存k个右端点,表示第i层当前的最远右端点,每次来一根新线段,能填就填进并更新,不能填就更新右端点,
线段seg 能填进当且仅当multiset的首元素<seg.s, 然后把这个首元素删除,更新为seg.t
反之找到multiset的尾元素,如果>seg.t,那么更新为seg.t
*/
#include<bits/stdc++.h>
#include<set>
using namespace std;
#define N 200005
struct Seg{int l,r,id;}seg[N];
int cmp(Seg a,Seg b){return a.l<b.l;}
multiset<pair<int,int> >s;
multiset<pair<int,int> >::iterator it,itt;
int n,k,has[N];
int main(){
cin>>n>>k;
for(int i=1;i<=n;i++){
cin>>seg[i].l>>seg[i].r;
seg[i].id=i;
}
sort(seg+1,seg+1+n,cmp);
for(int i=1;i<=k;i++)s.insert(make_pair(0,0));
int ans=0;
for(int i=1;i<=n;i++){
it=s.begin();
pair<int,int> tmp=*it;
if(tmp.first<seg[i].l){//能填进去
tmp.first=seg[i].r;
tmp.second=seg[i].id;
has[seg[i].id]=1;
s.insert(tmp);
s.erase(it);
ans++;
}
else {//不能填进去
itt=s.end();
itt--;
tmp=*itt;
if(tmp.first>seg[i].r){
tmp.first=seg[i].r;
has[tmp.second]=0;
has[seg[i].id]=1;
tmp.second=seg[i].id;
s.insert(tmp);
s.erase(itt);
}
}
}
cout<<n-ans<<'\n';
for(int i=1;i<=n;i++)
if(!has[i])cout<<i<<" ";
}
/*
9 11
7 8
7 8
9 11
*/