本题限制时间1s,而数据范围2e5,也就是说时间复杂度顶多 O ( n l o g n ) O(nlogn) O(nlogn)了,那就不能直接暴力枚举,可以使用双指针。
在使用双指针时要思考主要指针指向什么,在什么条件下能够更新另一个指针。
在本题中要找的是最大的友善值,并且要保证期望友善值得到满足,假如现在使得主指针扫描的是每个猫猫,那么另一个指针如果扫到了能达到期望的人,就把友善值取 m a x max max,然后去扫下一个人。
所以要对猫猫进行按照友善值升序排序,对人进行按照期望友善值升序排序,那么就可以实现以下操作:
- 枚举猫的时候是按照友善值升序,扫人的时候是按照期望友善值升序,如果当前猫友善值不如期望值高,那之后的人的期望值会更高,就更不会满足,所以 j j j 就不用再往后扫了,直接停住就可以。
- 过程中一直维护最大的友善值,当前扫到第j个人,取到的友善值是 1 1 1 ~ j j j部分最大的,每扫一个猫猫,猫猫的友善值都会更高,如果当前的猫猫满足了第j个人的期望,那么后面的猫猫一定都满足了。
- j j j 没必要重置回去,因为重置回去只可能导致人的最大的友善值,但是往后扫猫猫的期望友善值一定满足前j个,所以 j j j 往回走是完全没必要的
故此题可以进行双指针。
注意:
- 本题求解的时候要求按照原来读入时的顺序输出每个猫猫的答案,所以要确定好原始下标,以保证sort之后输出时不会乱序。
代码: 注:range
代表for循环
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
const int N = 2e5 + 10;
//a:start b:end c:step
#define range(i,a,b,c) for(int i = a;i <= b;i+=c) struct Node {int x, y; //x:友善值,y:期待友善值int id; //id:读入时候的下标
}cat[N], person[N];
int n, m;int main() {cin >> n >> m;vector<int>ans(n);//一串读入range(i, 1, n, 1) cin >> cat[i].x;range(i, 1, n, 1)cin >> cat[i].y;range(i, 1, m, 1) cin >> person[i].x;range(i, 1, m, 1)cin >> person[i].y;//初始化初始下标range(i, 1, n, 1)cat[i].id = i;range(i, 1, m, 1)person[i].id = i;sort(cat + 1, cat + 1 + n, [=](Node a, Node b) { //猫按照友善值升序排序return a.x < b.x;});sort(person + 1, person + 1 + m, [=](Node a, Node b) { //人按照期望友善值升序排序return a.y < b.y;});int j = 1,MM = -1e9;range(i,1,n,1) {//满足猫友善值大于等于人期望友善值的情况下,一直往后扫人while (cat[i].x >= person[j].y && j <= m) {MM = max(MM, person[j].x);//更新MM为最大的友善值j++;//往后扫}//友善值大于猫的期望友善值时if (MM >= cat[i].y) ans[cat[i].id] = MM;else ans[cat[i].id] = -1;}range(i, 1, n, 1) cout << ans[i] << " ";return 0;
}