0%

[題解]NEOJ 69 田忌賽馬(NPSC)

田忌賽馬(NPSC)

題目連結
之前有寫過這一題,不過現在再寫一次還是WA了很久,對於二分搜的維護(到底是取到0還是1)還要更熟悉
除此之外,我因為邊界問題($10^8$ 或是$10^8+1$)沒有仔細注意就一直WA

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
#include <bits/stdc++.h>
#define N 10000
using namespace std;
lli n,k,t,M,upper = 100000000,lower = -1;
lli mine[N],develop[N],enemy[N],curr[N];

bool win(lli day){
int it = 0,sum = 0;
for(int i=0;i<n;i++)
curr[i] = mine[i]+day*develop[i];
sort(curr, curr+n);
for(int i=0;i<n;i++){
if(curr[i]>enemy[it]){
sum++;
it++;
}
}
return (sum>=k);
}

int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cin>>t;
while(t--){
upper = 100000000;lower = -1;
cin>>n>>k;
for(int i=0;i<n;i++){
cin>>mine[i]>>develop[i];
}
for(int i=0;i<n;i++){
cin>>enemy[i];
}
sort(enemy, enemy+n);
if(!win(upper))cout<<-1<<endl;
else{
while(upper-lower!=1){
M = (upper+lower)/2;
if(win(M))upper = M;
else lower = M;
}
cout<<upper<<endl;
}
}
}

這樣維護二分搜也可以,就是保證 r 一定是1(l就不一定)

1
2
3
4
5
6
7
8
while(r>l){
int mid = (l+r)/2, arr[n+5];
for(int i=0;i<n;i++)arr[i] = mine[i]+mid*rate[i];
sort(arr, arr+n,greater<int>());
int f = can_win(arr, enemy);
if(f)r = mid;
else l = mid+1;
}

單純二分搜,找01分界點!