D2. Too Many Segments (hard version) (greedy + segment tree maintenance)

Question 2

Meaning of the questions:

    Given n intervals required to remove as little of each section such that the number of points to be covered is not more than 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

analysis:

    From left to right we judge each point satisfy a condition. For the left point conditions are not satisfied, deleted interval must be less than the current point. For these intervals can be deleted, apparently greedy deleting the right boundary farther range. So simulate this process can be, and delete the interval with maintenance tree line, each looking for the farthest range, with a priority queue to maintain.

#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;
} 


Published 132 original articles · won praise 6 · views 7922

Guess you like

Origin blog.csdn.net/weixin_44316314/article/details/104887636