题目大意:小苗给n个线段,往上边放点,要求所有点的x坐标不能相同,问最后能最多覆盖多少曲线。
题目思路:按照左端点排序再按照右端排序。简单贪心一想,应该是直接能取就取,也就是让当前取得x坐标,也就是pos直接+1,如果取不了就定义为下一段的L值,这样看着是可以的,但是可能会漏一些
比如:
1 1
1 3
2 2
这样排序后那个2 2的就被覆盖掉了,所以怎么才能不漏这个2呢,答案就是当贪心到这个地方的时候将2 2这段也作为贪心集合的一部分对吧。这样问题就解决了,在上边的错误贪心上就加一条,就是如果贪心的pos碰到某个左端点了,这个线段也要入贪心集合。所谓的贪心集合是不是就是包含pos的线段们啊,用优先队列维护r递增就好了。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll MAXN=1e5+5;
struct node
{
int l, r;
bool operator < (const node &a)const{
return r>a.r;
}
}C[MAXN];
bool cmp(node a,node b)
{
if(a.l==b.l){
return a.r<b.r;
}
return a.l<b.l;
}
priority_queue<node>q;
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d%d",&C[i].l,&C[i].r);
}
sort(C+1,C+1+n,cmp);
while(!q.empty())q.pop();
int pos=C[1].l,ans=0,index=1;
while(index<=n){
while(index<=n&&C[index].l<=pos&&pos<=C[index].r){//将包含pos的全部入队
q.push(C[index++]);
}
while(!q.empty()&&pos<C[index].l){ //让包含pos的逐个出队,pos在不断更新,不能涉及下一段的开始
if(pos<=q.top().r)pos++,ans++;
q.pop();
}
if(index!=n+1)pos=C[index].l;
}
while(!q.empty())//最后还没出队的要单独搞一下
{
if(pos<=q.top().r)ans++,pos++;
q.pop();
}
printf("%d\n",ans);
}
}