- 题解
Day2 T4 手术参考代码
- @ 2024-10-3 16:18:08
set用法:https://blog.csdn.net/yas12345678/article/details/52601454
set<pair<int, int>> s
s = {[1, 14]};
优先级最高的患者,需要用[8,9]--> t=8,b=2
s = {[1,7],[10,14]};
优先级第二高区间[4,5] --- 1
s = {[1,3], [6,7], [10,14]}
优先级第三高的区间[4,6] --- 2
s = {[1,3], [13,14]}
此处[6,7]也没用了,因为后面的患者如果插入到[6,7]会发生医闹。
#include<bits/stdc++.h>
using namespace std ;
int main()
{
freopen("op.in", "r", stdin);
freopen("op.out", "w", stdout);
std::ios::sync_with_stdio(false) , cin.tie(0) ;
int n , k ;
cin >> n >> k ;
vector<int> p(n + 1 , 0) ;
vector<int> t(n + 1 , 0) ;
vector<int> a(n + 1 , 0) ;
vector<int> b(n + 1 , 0) ;
for(int i = 1 ; i <= n ; i ++) cin >> p[i] ;
for(int i = 1 ; i <= n ; i ++) cin >> t[i] ;
for(int i = 1 ; i <= n ; i ++) cin >> a[i] ;
for(int i = 1 ; i <= n ; i ++) cin >> b[i] ;
vector<int> id(n + 1 , 0) ;
for(int i = 1 ; i <= n ; i ++) id[i] = i ;
sort(id.begin() + 1 , id.end() , [&](int x , int y)
{
return p[x] < p[y] ; // 匿名函数,等同于cmp函数,这里按p严重度小的排序
}) ;
set<pair<int , int>> s ;
s.insert({1 , k}) ; // 初始可以手术区间
long long res = 0 ;
for(int i = 1 ; i <= n ; i ++)
{
int c = id[i] ; // 当前优先级最高的病患编号
if(s.empty()) break ; // s为空说明结束
auto it = s.lower_bound({t[c] , 0}) ; // 返回>=t[c]的最小值
auto it2 = it ;
if(it2 != s.begin()) it2 -- ;
if(it2 -> first <= t[c] && t[c] <= it2 -> second) it = it2 ; // 找到可以安排手术的最早时间
if(it != s.end()) // 没有超出s边界
{
t[c] = max(t[c] , it -> first) ; // 安排手术的时间是 max(ti, 最早可做的时间)
if(t[c] <= it -> second) // it->second 是区间右端点,满足条件说明可以插入到此区间
{
if(it -> first < t[c]) // it-first 是区间左端点
{
// 此处的操作是:1.删除[l,r] 2.插入[l,t_i-1] [t_i, r]
// 以[1, 10] 插入[4,5] 为例,[1,10] --> [1, 3] [6, 10]
int l = it -> first ;
int r = it -> second ;
s.erase({l , r}) ;
s.insert({l , t[c] - 1}) ;
s.insert({t[c] , r}) ;
it = s.lower_bound({t[c] , 0}) ; // 更新可以安排手术的最早区间
}
vector<pair<int , int>> v ; // 用来存中间不可用需要删除的区间
while(it != s.end()) // 边界判断
{
int l = it -> first ;
int r = it -> second ;
if(r - l + 1 >= b[c]) // 区间长度大于手术时间,可以安排手术
{
res += a[c] ; // 收钱
s.erase(it) ; // 删除掉这段区间
if(r - l + 1 > b[c]) s.insert({l + b[c] , r}) ; // 插入更新后的区间
break ;
}
else
{
// 中间不可以插入的区间,也不能给后续的患者用了,否则会医闹
v.push_back({l , r}) ;
it ++ ;
}
}
for(auto now : v) s.erase(now) ; // 删除中间的无用区间
}
}
}
cout << res << '\n' ;
return 0 ;
}
6 条评论
-
cdlihanyu LV 4 @ 2024-10-3 22:32:22
真简单!(难啊!!!谁来教我!!!!!)👍 1 -
@ 2024-10-3 19:15:23我不会!!!!!!!!!!!!!!!!!
🤔 1 -
@ 2024-10-3 19:04:07太
简洁复杂了 -
@ 2024-10-3 16:37:35
前排👍 6 -
@ 2024-10-3 16:36:54qp
👍 7 -
@ 2024-10-3 16:35:43前排
🤡 10👍 7
- 1