D2. Too Many Segments (hard version)(贪心+线段树维护)

题目2

题意:

    给定n个区间,要求删除尽可能少的区间使得每个点被覆盖的次数不超过k。
     1 k n 2 1 0 5 1 l i r i 2 1 0 5 1≤k≤n≤2⋅10^5,1≤l_i≤r_i≤2⋅10^5

分析:

    我们从左到右判断每个点是否满足条件。对于不满足条件的,删的区间的左端点必须小于当前点。对于这些可以删的区间,显然贪心的删去右边界更远的区间。所以模拟这个过程就可以了,区间删除用线段树维护,每次找最远的区间,用一个优先队列来维护。

#include <iostream>
#include <queue>
#include <vector> 
#include <algorithm>
using namespace std;
typedef long long ll;

vector<int> ans;

struct seg{
	int id,l,r;
	bool operator<(const seg&s)const
	{
		return r < s.r;
	}
}s[200005];

bool cmp(seg a,seg b)
{
	return a.l < b.l;
}

struct node{                    
	ll l,r,sum,lazy;
}a[200005*4];

void update( int x )   
{
	a[x].sum = a[2*x].sum + a[2*x+1].sum;     
}

void build( int x,int l,int r )   
{
	a[x].l = l;
	a[x].r = r;
	if( l == r )   
	{
		a[x].sum = 0;
		return;
	}
	int mid = l + ( r - l ) / 2;    
	build(2*x,l,mid);              
	build(2*x+1,mid+1,r);
	update(x);                      
} 

void pushdown(int x)   
{
	if( a[x].l == a[x].r )
	{
		a[x].lazy = 0;
		return;
	}
	int left = 2*x;
	int right = 2*x+1;
	a[left].sum += ( a[left].r - a[left].l + 1 ) * a[x].lazy;
	a[right].sum += ( a[right].r - a[right].l + 1 ) * a[x].lazy;
	a[left].lazy += a[x].lazy;
	a[right].lazy += a[x].lazy;
	a[x].lazy = 0;
}

void change(int x,int l,int r,int k) 
{
	if( a[x].l == l && a[x].r == r )    
	{
		a[x].sum += (r-l+1) * k;   
		a[x].lazy += k;
		return;
	}
	if( a[x].lazy ) pushdown(x);     
	int mid = a[x].l + ( a[x].r - a[x].l ) / 2;
	if( r <= mid ) change(2*x,l,r,k);    
	else if( l > mid ) change(2*x+1,l,r,k); 
	else
	{
		change(2*x,l,mid,k);     
		change(2*x+1,mid+1,r,k);
	} 
	update(x);
} 

ll query(int x,int l,int r)  
{
	if( a[x].lazy ) pushdown(x);   
	if( a[x].l == l && a[x].r == r ) return a[x].sum;
	int mid = a[x].l + ( a[x].r - a[x].l ) / 2;
	if( r <= mid ) return query(2*x,l,r);  
	else if( l > mid ) return query(2*x+1,l,r);   
	else return query(2*x,l,mid) + query(2*x+1,mid+1,r);   
} 

int main()
{
	int n,k;
	cin >> n >> k;
	build(1,1,2e5);
	for (int i = 1; i <= n; i++)
	{
		cin >> s[i].l >> s[i].r;
		change(1,s[i].l,s[i].r,1);
		s[i].id = i;
	}
	sort(s+1,s+1+n,cmp);
	int index = 1;
	priority_queue<seg> q;
	for (int i = 1; i <= 2e5; i++)
	{
		while( index <= n && s[index].l <= i )
		{
			q.push(s[index]);
			index ++; 
		}
		int t = query(1,i,i);
		while( t > k )
		{
			seg z = q.top();
			q.pop();
			ans.push_back(z.id);
			change(1,z.l,z.r,-1);
			t --; 
		}
	}
	cout << ans.size() << '\n';
	for (int i = 0; i < ans.size(); i++)
	{
		cout << ans[i];
		if( i == ans.size() - 1 ) cout << '\n';
		else cout << ' ';
	}
	return 0;
} 


发布了132 篇原创文章 · 获赞 6 · 访问量 7922

猜你喜欢

转载自blog.csdn.net/weixin_44316314/article/details/104887636
今日推荐