题解:AT_abc214_e [ABC214E] Packing Under Range Regulations
lovely_qiqi · · 题解
问题陈述
给你一些球以及它们应该在的区间,每个点只能放一个球,问能否放完。(多测)
思路
这题首先想到贪心:合理放法,放左边比放右边更好,因为这样可以给后面的留下更多位置。
但一个一个遍历肯定超时。
所以我们需要一个数据结构来维护,它需要满足以下特点:
-
能高效的找出最值(这样才能判断会不会无解)
-
能高效的加入数值(每个元素都要尝试加进来)
这就是堆!
用堆维护右端点最小值即可,详情见代码。
#include<bits/stdc++.h>
#define endl '\n'
using namespace std;
struct node{
int l;
int r;
}a[200010];
bool cmp(node t1,node t2){return t1.l<t2.l;}
priority_queue<int,vector<int>,greater<int>> h;
int t,n,al,now;
bool flag;
int main(){
cin.tie(0),cout.tie(0);
ios::sync_with_stdio(false);
cin>>t;
while(t--){
flag=false;//标记
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i].l>>a[i].r;
sort(a+1,a+1+n,cmp);//按左端点升序排序,贪心
al=0,now=0;//L
while(h.size()) h.pop();////多测不清空,亲人两行泪
while(now<n){//遍历
if(h.empty()){//如果是空的就压进来,不然就是空的,无法进行之后的操作。
al=a[++now].l;
h.push(a[now].r);
}
while(now<n&&a[now+1].l<=al){//如果下一个在al之前,那无需更新,直接加入即可,但是最后可能将al遍历了,所以要+1
h.push(a[++now].r);
}
if(h.top()<al){/如果当前右端点小于左端点,无解
cout<<"No"<<endl;
flag=true;
break;
}
al++;
h.pop();
}
if(flag==true) continue;
while(!h.empty()){////如果里面还有没被处理的区间,那就按之前的方法处理即可。
if(h.top()<al){
cout<<"No"<<endl;
flag=true;
break;
}
al++;
h.pop();//当前的处理完了,pop掉,不然可能干扰后续操作
}
if(flag==false) cout<<"Yes"<<endl;
}
return 0;
}