[HNOI2004]宠物收养场 题解 set
题目链接:https://www.luogu.com.cn/problem/P2286
题目大意:
有 \(N(N \le 80000)\) 只宠物或领养者依次来到宠物收养场,他们都有一个特征值。
当有一只宠物进入收养场时,如果存在等待的领养者,会从领养者中挑选和宠物特征值最接近的领养者匹配(然后离开收养场);否则,宠物等待。
当有一个领养者进入收养场时,如果存在等待的宠物,会从宠物中挑选和领养者特征值最接近的宠物匹配(然后离开收养场);否则,领养者等待。
每次匹配,答案都会加上匹配的宠物和领养者的差的绝对值,求答案。
解题思路:
首先这种边界性问题考虑用二分解决。
但是数据是动态的(动态插入和删除),所以考虑用集合(set)来维护数据,然后在set上进行二分。
实现代码如下:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 80080, MOD = 1000000;
set<int> pets, owners;
int n, ans, op, a;
void solve(set<int> &st, int a) {
if (st.size() == 1) {
ans = (ans + abs(a - (*st.begin()))) % MOD;
st.clear();
}
else {
set<int>::iterator r = st.lower_bound(a);
if (r == st.begin()) {
ans = (ans + abs(a - (*st.begin()))) % MOD;
st.erase(r);
}
else {
set<int>::iterator l = --st.lower_bound(a);
if (r == st.end() || abs(a - *l) <= abs(a - *r)) {
ans = (ans + abs(a - (*l))) % MOD;
st.erase(l);
}
else {
ans = (ans + abs(a - (*r))) % MOD;
st.erase(r);
}
}
}
}
int main() {
scanf("%d", &n);
while (n --) {
scanf("%d%d", &op, &a);
if (op == 0) {
if (owners.size() == 0) pets.insert(a);
else solve(owners, a);
}
else {
if (pets.size() == 0) owners.insert(a);
else solve(pets, a);
}
}
printf("%d\n", ans);
return 0;
}