abc214_e Packing Under Range Regulations(贪心)
题目大意
给你n个区间,让你每个区间选一个数,选的数不能重复。
解题思路
看到题的第一眼肯定是想大力贪。怎么贪呢?对于每个区间来说,尽可能的选靠左或者靠右的数?好像都不太对的样子。
我们考虑将所有区间的左端点排序,然后用一个指针从最小的左端点往右移,每存在一个以当前指针为左端点的右端点就把他们加进一个集合里,可以看出,当前指针的位置都是被在集合里的右端点对应的区间所包含的,那我们就取集合中最小的那个右端点删掉,左端点+1。如果遇见左端点比集合最小的右端点大的情况,说明肯定是放不下了,否则的话重复到集合为空为止。集合为空时再用一个比当前指针大的最小的左端点替换掉当前指针的位置,继续上面操作。
const int maxn = 2e5+10;
const int maxm = 1e6+10;
map<int, vector<int>> mp;
int main() {
IOS;
int __; cin >> __;
while(__--) {
int n; cin >> n;
set<int> st; st.insert(INF);
for (int i = 1; i<=n; ++i) {
int a, b; cin >> a >> b;
mp[a].push_back(b);
st.insert(a);
}
priority_queue<int, vector<int>, greater<int> > pq;
bool ok = 1;
int now = *st.begin();
while(ok && now<INF) {
for (auto v : mp[now]) pq.push(v);
int t = pq.top(); pq.pop();
if (now>t) ok = 0;
else if (pq.empty()) {
auto p = st.upper_bound(now);
now = *p;
}
else ++now;
}
cout << (ok ? "Yes":"No") << endl;
mp.clear();
}
return 0;
}