第三题:MAXIMIZING PRODUCTIVITY
标签:二分查找、思维
题意:给定
N
N
N个农场,第
i
i
i个农场在
c
i
c_i
ci的时候关闭。
B
e
s
s
i
e
Bessie
Bessie在时间
S
S
S的时候起床,计划在
t
i
+
S
t_i+S
ti+S的时间访问第
i
i
i个农场,必须在农场关闭之前去访问。进行
Q
Q
Q次查询,每次给出
S
S
S和
V
V
V,求是否能在时间
S
S
S的时候起床,并访问至少
V
V
V个农场。
(
1
≤
S
,
N
≤
1
0
6
,
1
≤
c
i
,
t
i
≤
1
0
6
,
1
≤
V
<
=
N
1≤S,N≤10^6,1≤c_i,t_i≤10^6,1≤V<=N
1≤S,N≤106,1≤ci,ti≤106,1≤V<=N)
二分查找解法 题解:因为查询次数比较多,直接暴力模拟 肯定会超时,我们需要做一些优化处理。题目中要求在农场关闭之前访问,所以我们可以把数组
c
c
c减去数组
t
t
t求个差值 再减一(因为题目要求关闭之前),求出第
i
i
i个如果要访问到,最迟的起床时间。然后对差值数组进行一下排序。
比如排序后的差值数组是:
−
3
、
2
、
4
、
7
、
10
、
15
-3、2、4、7、10、15
−3、2、4、7、10、15
假定当前查询的
S
=
4
,
V
=
3
S=4,V=3
S=4,V=3,那么可以通过二分找到第
3
3
3个位置,那么从这个位置往后到第
N
N
N个的位置都是可以访问到的,记
N
−
P
+
1
N-P+1
N−P+1个。(
P
P
P表示通过
l
o
w
e
r
_
b
o
u
n
d
lower\_bound
lower_bound函数找到的第一个大于等于
S
S
S的位置),然后我们与对应要求个数的
V
V
V对比判定一下输出即可。
二分查找解法 代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
int c[N], t[N], v, s, n, q;
int main() {
cin >> n >> q;
for (int i = 1; i <= n; i++) cin >> c[i];
for (int i = 1; i <= n; i++) {
cin >> t[i];
c[i] = c[i] - t[i] - 1;
}
sort(c + 1, c + 1 + n);
while (q--) {
cin >> v >> s;
int p = lower_bound(c + 1, c + 1 + n, s) - c;
if (n - p + 1 >= v) cout << "YES" << endl;
else cout << "NO" << endl;
}
return 0;
}
思维解法 题解:和二分查找解法类似,因为题目中要求在农场关闭之前访问,所以我们可以把数组
c
c
c减去数组
t
t
t求个差值,再减一(因为题目要求关闭之前),然后对差值数组进行一下从大到小排序。
比如排序后的差值数组是:
15
、
10
、
7
、
4
、
2
、
−
3
15、10、7、4、2、-3
15、10、7、4、2、−3
假定当前查询的
S
=
4
,
V
=
3
S=4,V=3
S=4,V=3,判定 发现差值数组的第
3
3
3 个位置的值大于等于
S
S
S,那说明前
V
V
V个都能到达。如果同学们在做差值数组的时候没有减一,这边判大于就可以了。
思维解法 代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
int c[N], t[N], v, s, n, q;
bool cmp(int x, int y) {
return x > y;
}
int main() {
cin >> n >> q;
for (int i = 1; i <= n; i++) cin >> c[i];
for (int i = 1; i <= n; i++) {
cin >> t[i];
c[i] = c[i] - t[i] - 1;
}
sort(c + 1, c + 1 + n, cmp);
while (q--) {
cin >> v >> s;
if (c[v] >= s) cout << "YES" << endl;
else cout << "NO" << endl;
}
return 0;
}