APIO2023 线上游记

  • ~1.51K 字
  1. 1. 分析
  2. 2. 代码
  3. 3. 闲话

“请告诉我为何心不停的跳动 这颗心究竟装着什么” —— 《人偶之梦》

分析

注意到 pi<pjp_i<p_jcicjc_i\leq c_j,存在偏序关系。

一个贪心的想法是,按照订单的 vv 从大到小,每次找到大于 dd 的最小的 pp 住进去。

但是如果房间已经被占用,就住进大于 ddpp 最小的没有被占用的房间,而不是把占用清除。

考虑这样为什么是对的,设占用房间的为 ii,要住进去的为 jj

  • 如果 i,ji,j 都要入住,答案无影响。
  • 如果 i,ji,j 只有一个要入住,因为 vi>vjv_i>v_j,所以 ii 肯定比 jj 更优,jj 必定不会被选到(就选选的不是最优的房间也不影响)。

现在问题变成了,找到大于 ddpp 最小的没有被占用的房间,然后把这个房间删除,multiset 可以解决(注意房间可重,set 不可重)。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
multiset<pair<int,int>> house;
vector<pair<int,int>> order;
int n,m,o;

int main(){
n = in(),m = in(),o = in();
for(int k=1;k<=n;k++){
int c = in(),p = in();
house.insert({p,c});
}
order.resize(m);
for(auto &[v,d]:order)
v = in(),d = in();
sort(order.begin(),order.end(),[](auto a,auto b){return a.first!=b.first?a.first>b.first:a.second<b.second;});
vector<int> res;
for(auto [v,d]:order){
auto it = house.lower_bound({d,0});
if(it!=house.end()){
if(v<=(*it).second)
continue;
res.push_back(v-(*it).second);
house.erase(it);
}
}
sort(res.begin(),res.end(),greater<>());
long long ans = 0;
for(int k=0;k<min(o,(int)res.size());k++)
ans += res[k];
out(ans);
return 0;
}

闲话

pi<pjp_i<p_jcicjc_i\leq c_j 放在题面更合理吧,放在数据范围有点抽象。