查询数字的最邻近

 

 

 

 这道题目要用二分+桶排的方式解决

函数:

l~r找v

c:靠左/右(‘l’/‘r’)

 

 

靠左和靠右用STL函数二分就行,这里讲一下思路,二分出最靠左/右的v值(but二维,在but[v][0~len]区间二分)再判断是否在区间内在区间内输出but[v][a](a为二分的答案)否则输出-1。

靠左:用lower_bound第一种格式,因为要找最靠左的也就是第一个在but[v]所表示的值中大于或等于l的值。

靠右:用upper_bound第一种格式,我们可以先找到第一个在but[v]所表示的值中大于r的值再减一即是答案因为二分答案有一个性质就是答案的左边一格及再往左一定是不满足要求的,所以可以这样做。

最后再考虑一下需要输出-1的特殊情况(区间内没有v、不合法..........等)即可

主函数:

输入并预处理二维桶(but[i][j]表示i第j次出现的位置) 若输入为a[i]则预处理为v[a[i]].push_back(i);这就可以看出来vector 的优势了,直接推就行不用考虑推到哪。

最后调用函数即可

例程:

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
vector<int > but[N];
int n,m;
int e_f(int l,int r,int v,char c)
{
    if(l>r||but[v].size()==0||l<=0||r>n) return -1;
    if(c=='l')
    {
        int a=lower_bound(but[v].begin(),but[v].end(),l)-but[v].begin();
        if(but[v][a]>=l&&but[v][a]<=r) return but[v][a];
        else return -1;
    }
    else if(c=='r')
    {
         int a=upper_bound(but[v].begin(),but[v].end(),r)-but[v].begin();
         a-=1;
         if(but[v][a]>=l&&but[v][a]<=r) return but[v][a];
         else return -1;
    }
}
int main()
{
#ifdef LOCAL
    freopen( "1.in", "r", stdin );
    freopen( "1.out", "w", stdout );
#endif
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        int t;
        scanf("%d",&t);
        but[t].push_back(i);
    }
    while(m--)
    {
        int l,r,v;
        scanf("%d%d%d",&l,&r,&v);
        int a1=e_f(l,r,v,'l');
        int a2=e_f(l,r,v,'r');
        int a3=e_f(1,l-1,v,'r');
        int a4=e_f(r+1,n,v,'l');
        printf("%d %d %d %d\n",a1,a2,a3,a4);        
    }
    return 0;
}

 

posted @ 2022-09-04 21:14  王浩泽  阅读(76)  评论(0编辑  收藏  举报