NC249989 猫猫与主人 (双指针,排序)

在这里插入图片描述
在这里插入图片描述
本题限制时间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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值