题解:P11109 [ROI 2023] 会议 (Day 2)
原题链接
- 洛谷 P11109 [ROI 2023] 会议 (Day 2)
题意简述
有
解题思路
妙妙题。
首先考虑我们该如何选择区间,经典对区间右端点排序并贪心选择。
注意到在选区间的过程中,两两被选择的区间
因此我们只要在初始的
由于我们要取的是
参考代码
#include <bits/stdc++.h>
using namespace std;
const int N = 100005;
int T , n , nxt[N];
vector <int> v , ans;
struct point{int l , r , id;} p[N];
signed main()
{
cin.tie(nullptr)->sync_with_stdio(false);
cin >> T;
while(T--)
{
cin >> n;
for(int i = 1 ; i <= n ; i++) cin >> p[i].l >> p[i].r , p[i].id = i;
sort(p + 1 , p + n + 1 , [](point x , point y){return x.r < y.r;});
int lst = 0; v.clear();
for(int i = 1 ; i <= n ; i++) if(p[lst].r < p[i].l)
{
if(lst) nxt[lst] = i;
v.emplace_back(i) , lst = i;
}
nxt[lst] = n + 1; ans.clear();
// for(auto x : v) cout << x << ' '; cout << '\n';
sort(v.begin() , v.end() , [](int x , int y){return nxt[x] - x > nxt[y] - y;});
for(int i = 0 ; i < v.size() >> 1 ; i++) ans.emplace_back(v[i]);
for(int i = 0 ; i < v.size() >> 1 ; i++)
{
if(ans.size() == n >> 1) break;
for(int j = v[i] + 1 ; j < nxt[v[i]] ; j++)
{
ans.emplace_back(j);
if(ans.size() == n >> 1) break;
}
}
for(auto x : ans) cout << p[x].id << ' '; cout << '\n';
}
return 0;
}