第三题:MAXIMIZING PRODUCTIVITY
标签:二分查找、思维
题意:给定NNN个农场,第iii个农场在cic_ici的时候关闭。BessieBessieBessie在时间SSS的时候起床,计划在ti+St_i+Sti+S的时间访问第iii个农场,必须在农场关闭之前去访问。进行QQQ次查询,每次给出SSS和VVV,求是否能在时间SSS的时候起床,并访问至少VVV个农场。
(1≤S,N≤106,1≤ci,ti≤106,1≤V<=N1≤S,N≤10^6,1≤c_i,t_i≤10^6,1≤V<=N1≤S,N≤106,1≤ci,ti≤106,1≤V<=N)
二分查找解法 题解:因为查询次数比较多,直接暴力模拟 肯定会超时,我们需要做一些优化处理。题目中要求在农场关闭之前访问,所以我们可以把数组ccc减去数组ttt求个差值 再减一(因为题目要求关闭之前),求出第iii个如果要访问到,最迟的起床时间。然后对差值数组进行一下排序。
比如排序后的差值数组是:−3、2、4、7、10、15-3、2、4、7、10、15−3、2、4、7、10、15
假定当前查询的S=4,V=3S=4,V=3S=4,V=3,那么可以通过二分找到第333个位置,那么从这个位置往后到第NNN个的位置都是可以访问到的,记N−P+1N-P+1N−P+1个。(PPP表示通过lower_boundlower\_boundlower_bound函数找到的第一个大于等于SSS的位置),然后我们与对应要求个数的VVV对比判定一下输出即可。
二分查找解法 代码:
#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;
}
思维解法 题解:和二分查找解法类似,因为题目中要求在农场关闭之前访问,所以我们可以把数组ccc减去数组ttt求个差值,再减一(因为题目要求关闭之前),然后对差值数组进行一下从大到小排序。
比如排序后的差值数组是:15、10、7、4、2、−315、10、7、4、2、-315、10、7、4、2、−3
假定当前查询的S=4,V=3S=4,V=3S=4,V=3,判定 发现差值数组的第 333 个位置的值大于等于SSS,那说明前VVV个都能到达。如果同学们在做差值数组的时候没有减一,这边判大于就可以了。
思维解法 代码:
#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;
}