0%

D. Sharky Surfing

思路讲解

主要思路就是使用二叉堆的一个贪心(pq)

把这个障碍物前面的全部奖励都放到pq里,然后用一个弹出一个,避免后面重复用,还有一个就是降低算法复杂度

其实还有一个对于算法复杂度的一个判断

其实push pq不用担心时间复杂度的问题,因为用过的我们都会push掉,所以每个奖励我们只会遍历一次,所以差不多是O(nlogn+mlogm)

AC代码

https://codeforces.com/contest/2037/submission/293963686

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
#include <iostream>
#include <cstring>
#include <algorithm>
#include <deque>
#include <queue>
#include <vector>
#include <set>
#include <map>
#include <cmath>
#include <bitset>
#include <iterator>
#include <random>
#include <iomanip>

using namespace std;
typedef long long ll;
const ll N=static_cast<ll>(2e5)+10;
ll n,T,m,L;

int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>T;
while (T--) {
cin>>n>>m>>L;
vector<pair<ll,ll> > ban(n+5),enc(m+5);
vector<ll> senc(m+5,0);
priority_queue<ll> q;
for(int i=1;i<=n;++i){
cin>>ban[i].first>>ban[i].second;
}
for(int i=1;i<=m;++i){
cin>>enc[i].first>>enc[i].second;
}
for(int i=1;i<=m;++i)
senc[i]=senc[i-1]+enc[i].second;
// 跑一个greedy就行
ll sadd=1; // 起始push
ll curk=1; // 当前跳跃能力
ll ans=0;
bool isBreak=false;
for(int i=1;i<=n;++i){
ll len=ban[i].second-ban[i].first+1;
if(curk>len){ // 说明跳得过去
continue;
}
ll idx=lower_bound(enc.begin() + 1, enc.begin() + m + 1,make_pair(ban[i].first,0LL))-enc.begin()-1;
if(senc[idx]+1<=len){
cout<<-1<<endl;
isBreak=true;
break;
}
// 其实push pq不用担心时间复杂度的问题,因为用过的我们都会push掉,分摊一下就是O(n)
for(int i=sadd;i<=idx;++i){
q.push(enc[i].second);
}
while(!q.empty()){
curk+=q.top();
q.pop();
++ans;
if(curk>len)
break;
}
sadd=idx+1;
}
if(!isBreak)
cout<<ans<<endl;
}
return 0;
}
// AC https://codeforces.com/contest/2037/submission/293963686

心路历程(WA,TLE,MLE……)

二分搜索vector记得这么写

1
ll idx=lower_bound(enc.begin() + 1, enc.begin() + m + 1,make_pair(ban[i].first,0LL))-enc.begin()-1;