You are given array a with n integers and m queries. The i-th query is given with three integers li, ri, xi.
For the i-th query find any position pi (li ≤ pi ≤ ri) so that api ≠ xi.
The first line contains two integers n, m (1 ≤ n, m ≤ 2·105) — the number of elements in a and the number of queries.
The second line contains n integers ai (1 ≤ ai ≤ 106) — the elements of the array a.
Each of the next m lines contains three integers li, ri, xi (1 ≤ li ≤ ri ≤ n, 1 ≤ xi ≤ 106) — the parameters of the i-th query.
Print m lines. On the i-th line print integer pi — the position of any number not equal to xi in segment [li, ri] or the value - 1 if there is no such number.
6 4 1 2 1 1 3 5 1 4 1 2 6 2 3 4 1 3 4 2
2 6 -1 4
题目大意:
给你一个长度为N的序列Ai,有m个查询,每个查询三个元素:l,r,x,表示我们希望在序列区间【l,r】中,找到一个位子p,使得Ap!=x.
找到任意一个即可,如果找不到,输出-1.
思路:
1、首先我们设定<vector>mp【i】,我们将数字i所在的位子按照从小到大的顺序存入到这里.然后我们对于每个查询,因为数组具有单调性,我们可以二分第一个x出现的位子L.
①我们如果L是找不到的,那么对应肯定结果输出l即可。
②如果我们可以找到一个位子L,但是L!=l,那么对应结果肯定输出l即可。
③如果我们可以找到一个位子L,使得L==l,那么我们要查询位子L的右边,第一个不等于x的数的位子即可,如果这个位子<=R,那么输出这个位子,相反输出-1.
2、对于上述③中的查询,查询a【L】右边第一个不等于a【L】的位子,我们设定pos【i】来完成这个任务,那么对应O(n)从n扫到1预处理这个数组即可。
具体实现参考代码,并不复杂。
Ac代码:
#include<stdio.h>
#include<string.h>
#include<vector>
using namespace std;
vector<int >mp[1205000];
int a[205000];
int pos[205000];
int main()
{
int n,m;
while(~scanf("%d%d",&n,&m))
{
for(int i=1;i<=120000;i++)mp[i].clear();
for(int i=1;i<=n;i++)scanf("%d",&a[i]),mp[a[i]].push_back(i);
int nex=n;
for(int i=n;i>=1;i--)
{
if(i==n)pos[i]=n+1;
else
{
if(a[i]==a[i+1])pos[i]=pos[i+1],nex=i;
else pos[i]=nex,nex=i;
}
}
while(m--)
{
int L,R,x;
scanf("%d%d%d",&L,&R,&x);
int anspos=-1;
int l=0;
int r=mp[x].size()-1;
while(r-l>=0)
{
int mid=(l+r)/2;
// printf("%d %d\n",mid,mp[x][mid]);
if(mp[x][mid]>=L)
{
anspos=mp[x][mid];
r=mid-1;
}
else
{
l=mid+1;
}
}
if(anspos==-1)printf("%d\n",L);
else
{
if(anspos!=L)printf("%d\n",L);
else
{
if(pos[anspos]<=R)printf("%d\n",pos[anspos]);
else printf("-1\n");
}
}
}
}
}