题目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
1≤k≤n≤2⋅105,1≤li≤ri≤2⋅105
分析:
我们从左到右判断每个点是否满足条件。对于不满足条件的,删的区间的左端点必须小于当前点。对于这些可以删的区间,显然贪心的删去右边界更远的区间。所以模拟这个过程就可以了,区间删除用线段树维护,每次找最远的区间,用一个优先队列来维护。
#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;
}