Codeforces 622C Not Equal on a Segment (stl, 二分查找)

stl, 二分查找
题目意思:
有一个整数数组 a(元素最多 n <= 2e5), 有 m 次查询 ,每次给出三个数 L, R, p;
要求在 坐标[L, R] 范围内,找到一个下标 k ,使得 a[k] != p 。每次输出k, 如果找不到,就输出 -1;

本题要点:
1、 vector v[MaxN];
用 vector 数组a的每一个数 a[i] 在数组a中的下标。 v[a[i]].push_back(i);
然后 在 v[a[i]] 里面,存的所有下标是从小到大排序的。 有序后就可以二分了。
2、一些特判。
如果 L == R, 直接看 a[L] 是否等于 p;
如果 v[p].size() == 0, 说明p根本不在a数组出现,直接输出 L;
如果 v[p].size() == 0, 并且 L < R 的情况,看看 a[L], a[R] 与 p的关系即可。
还有看看 [L, R]是否在 p 的所有的下标范围内,如果 [L, R] 超出了其范围,看看L 和 v[p][0],
R和 v[p][len - 1] 的关系即可判断。
3、普遍的情况
v[p][0] <= L && R <= v[p][len - 1]。 [L, R]在 p 的所有的下标范围内。
用 lower_bound 分别找到 L, R 在 v[p] 中出现的下标 dx , dy;
如果, p 在数组a中的 [L, R] 的范围内都出现, 必然有 v[dx] == L && v[dy] == R, 并且 R - L == dy - dx;
如果不是连续出现,满足 v[dx] == L && v[dy] == R, 而 R - L > dy - dx, 需要找到第一个 a[k] != p 的下标,
使用二分查找, 在v[p] 中,[dx, dy] 范围内,找到第一个 满足 v[p][k] - k > L - dx 的 k 坐标。
v[p][k] - 1 , 肯定是满足 a[k] != p 的下标。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
const int MaxN = 1e6 + 10;
int a[MaxN];
int n, m;
int l, r, p;
vector<int> v[MaxN];

int solve()
{
	if(l == r)
	{
		if(a[l] == p)	return -1;
		else	return l;
	}
	int len = v[p].size();
	if(0 == len)
		return l;
	if(len == 1)
	{
		if(a[l] != p)	return l;
		if(a[r] != p)	return r;
	}
	if(v[p][0] > l)	return l;
	if(v[p][len - 1] < r)	return r;
	int dx = lower_bound(v[p].begin(), v[p].end(), l) - v[p].begin();
	if(v[p][dx] != l)	return l;	
	int dy = lower_bound(v[p].begin(), v[p].end(), r) - v[p].begin();	
	if(v[p][dy] != r)    return r;
	if(dy - dx == r - l)	return -1;
	int step = l - dx;
	int L = dx, R = dy, mid = 0;
	while(L < R)
	{
		mid = (L + R) / 2;	
		if(v[p][mid] - mid > step)
		{
			R = mid;		
		}else{
			L = mid + 1;
		}
	}
	return v[p][L] - 1;
}

int main()
{
	scanf("%d%d", &n, &m);
	for(int i = 1; i <= n; ++i)
	{
		scanf("%d", &a[i]);
		v[a[i]].push_back(i);
	}
	for(int i = 0; i < m; ++i)
	{
		scanf("%d%d%d", &l, &r, &p);
		printf("%d\n", solve());
	}
	return 0;
}

/*
6 4
1 2 1 1 3 5
1 4 1
2 6 2
3 4 1
3 4 2
*/

/*
2
6
-1
4
*/

猜你喜欢

转载自blog.csdn.net/qq_38232157/article/details/108451515