D2。あまりにも多くのセグメント(ハードバージョン)(貪欲+セグメントツリーのメンテナンス)

質問2

質問の意味:

    与えられたn個の間隔は、ポイント数が覆われるように、各セクションのほとんどは、よりkよりないように除去するために必要。
     1 K n個 2 1 0 5 1 リットル R 2 1 0 5 ^ 51≤k≤n≤2⋅10^5,1≤l_i≤r_i≤2⋅10

分析:

    左から右に、我々は、各点が条件を満たして判断します。左の点の条件が満たされていないために、削除された間隔が少ない現在のポイント以上でなければなりません。これらの間隔のための右の境界遠く範囲を削除、明らかに貪欲削除することができます。だから、それぞれが維持するために、プライオリティキューで、最も遠い範囲を探して、このプロセスがあること、およびメンテナンスツリーラインとの間隔を削除することができますシミュレートします。

#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