Codeforces Round #595 (Div. 3) D题

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;
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值