Too Many Segments (hard version)
The only difference between easy and hard versions is constraints.
You are given n segments on the coordinate axis OX. Segments can intersect, lie inside each other and even coincide. The i-th segment is [li;ri] (li≤ri) and it covers all integer points j such that li≤j≤ri.
The integer point is called bad if it is covered by strictly more than k segments.
Your task is to remove the minimum number of segments so that there are no bad points at all.
Input
The first line of the input contains two integers n and k (1≤k≤n≤2⋅105) — the number of segments and the maximum number of segments by which each integer point can be covered.
The next n lines contain segments. The i-th line contains two integers li and ri (1≤li≤ri≤2⋅105) — the endpoints of the i-th segment.
Output
In the first line print one integer m (0≤m≤n) — the minimum number of segments you need to remove so that there are no bad points.
In the second line print m distinct integers p1,p2,…,pm (1≤pi≤n) — indices of segments you remove in any order. If there are multiple answers, you can print any of them.
贪心+线段树;
1.首先要明确贪心的思想,先把区间排好序,按R从小到大排,如果R相等,那么L大的优先
2.那么会很明显想到,对于排好序的区间进行加1的操作,每次操作完后判断总区间的最大值是否大于k;如果大于k,那么记录这个区间并还原操作前的区间,也就是在-1操作;
3.怎么维护上面的操作呢,最容易想到的就是线段树了;
总结:
这种维护区间最大值,然后带区间修改的线段树竟然写的这么艰难(好久没写线段树了),属实不行了;
代码:
#include<bits/stdc++.h>
#define LL long long
#define pa pair<int,int>
#define lson k<<1
#define rson k<<1|1
//ios::sync_with_stdio(false);
using namespace std;
const int N=200100;
const int M=50100;
const LL mod=1e9+7;
int x,y,z;
struct Nod{
int l,r,f,mmax;
}tr[N<<2];
inline void build(int k,int ll,int rr){
tr[k].f=0,tr[k].l=ll,tr[k].r=rr,tr[k].mmax=0;
if(ll==rr) return;
int mid=(ll+rr)>>1;
build(lson,ll,mid);
build(rson,mid+1,rr);
}
inline void pd(int k){
if(tr[k].f){
tr[lson].f+=tr[k].f;
tr[lson].mmax+=tr[k].f;
tr[rson].f+=tr[k].f;
tr[rson].mmax+=tr[k].f;
tr[k].f=0;
}
}
inline void update(int k){
if(tr[k].l>=x&&tr[k].r<=y){
tr[k].mmax+=z;
tr[k].f+=z;
return;
}
pd(k);
int mid=(tr[k].l+tr[k].r)>>1;
if(x<=mid) update(lson);
if(y>mid) update(rson);
tr[k].mmax=max(tr[lson].mmax,tr[rson].mmax);
}
inline int ask(int k){
if(tr[k].l>=x&&tr[k].r<=y) return tr[k].mmax;
pd(k);
int M1=0,M2=0;
int mid=(tr[k].l+tr[k].r)>>1;
if(x<=mid) M1=ask(lson);
if(y>mid) M2=ask(rson);
return max(M1,M2);
}
struct Node{
int l,r,post;
}an[N];
bool cmp(Node p,Node q){
if(p.r==q.r) return p.l>q.l;
return p.r<q.r;
}
int main(){
ios::sync_with_stdio(false);
int n,k;
cin>>n>>k;
int Max=0;
for(int i=1;i<=n;i++){
cin>>an[i].l>>an[i].r;
Max=max(Max,an[i].r);
an[i].post=i;
}
build(1,1,Max);
int ans=0;
int s[N];
sort(an+1,an+1+n,cmp);
for(int i=1;i<=n;i++){
x=an[i].l,y=an[i].r;
z=1;
update(1);
x=1,y=Max;
if(ask(1)>k){
s[++ans]=an[i].post;
x=an[i].l,y=an[i].r;
z=-1;
update(1);
}
}
cout<<ans<<endl;
sort(s+1,s+ans+1);
for(int i=1;i<=ans;i++){
cout<<s[i]<<" ";
}
return 0;
}