• Hrbust-1830 第一个重复出现的数(线段树区间最值查询)


    Description
    给出n个数,问你在区间[a,b]内从右到左第一个出现重复的数字是哪一个。

    Input
    每组样例第一行给出n,表示有n个数(3≤ n ≤ 500,000)。

    第二行给出n个数,每个数不大于2^31。

    然后给出一个Q,表示有Q次询问 (1 ≤ Q ≤ 50,000)。

    接下来Q行每行两个数a,b (1 <= a < b <= n)。

    Output
    输出每次询问在[a,b]区间内第一次出现重复的数字是哪个,如果没有则输出”jiong”。

    每一组样例后输出一个换行。

    Sample Input

    5

    1 2 3 1 2

    3

    1 4

    1 5

    3 5

    6

    1 2 3 3 2 1

    4

    1 4

    2 5

    3 6

    4 6

    Sample Output
    1

    2

    jiong

    3

    3

    3

    jiong

    要从在区间L到R内找到第一个重复出现的的数,并且是从R遍历到L的过程中找到的第一个数,我们预处理出每一个数的上一次出现的位序,直接按值大小sort然后遍历找位序,再按位序sort回来,建立线段树,于是在线段树我们查询区间最大值,这个最大值即区间中第一次出现的重复的数的最近位置。检查这个值是否存在,若存在检查是否在区间内,符合条件直接输出即可

    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    using namespace std;
    struct num
    {
        int i,num,next;
    }a[500005];
    struct node
    {
        int l,r,maxx;
    }tree[500005*4];
    bool cmp(num a,num b)
    {
        if(a.num==b.num)return a.i<b.i;
        return a.num<b.num;
    }
    bool cmp2(num a,num b)
    {
        return a.i<b.i;
    }
    void build(int l,int r,int root)///建树
    {
        tree[root].l=l;
        tree[root].r=r;
        tree[root].maxx=-1;
        if(l==r)
        {
            tree[root].maxx=a[l].next;
        }
        else
        {
            int mid=(l+r)/2;
            build(l,mid,root*2);
            build(mid+1,r,root*2+1);
            tree[root].maxx=max(tree[root*2].maxx,tree[root*2+1].maxx);
        }
    }
    int query(int l,int r,int root)
    {
        if(l<=tree[root].l&&tree[root].r<=r)
        {
            return tree[root].maxx;
        }
        else
        {
            int mid = (tree[root].l+tree[root].r)/2;
            int res=-1;
            if(l<=mid)
            {
                res = max(query(l,r,root*2),res);
            }
            if(r>=mid+1)
            {
                res = max(query(l,r,root*2+1),res);
            }
            return res;///返回最大值
        }
    }
    int main()
    {
        int n;
        while(scanf("%d",&n)!=EOF)
        {
            for(int i=1;i<=n;i++)
            {
                scanf("%d",&a[i].num);
                a[i].i=i;
            }
            sort(a+1,a+n+1,cmp);///按数的大小排序,得到相同数的位序,然后错位赋值前一个相同元素的位序
            for(int i=n;i>=2;i--)
            {
                if(a[i].num==a[i-1].num) a[i].next=a[i-1].i;
                else a[i].next=-1;
            }
            sort(a+1,a+1+n,cmp2);///将打乱顺序的数列按恢复成原序列(位序排序)
            build(1,n,1);///将按顺序排列好并赋值了相同数下一位序的数组建立到线段树中
            int q,l,r;
            scanf("%d",&q);
            while(q--)
            {
                scanf("%d%d",&l,&r);///线段树最大值查询
                int ans=query(l,r,1);
                if(ans==-1||ans<l)printf("jiong
    ");
                else printf("%d
    ",a[ans].num);
            }
            printf("
    ");
        }
    }
    
  • 相关阅读:
    PHP获取指定的时间戳
    Elasticsearch
    git有用基本指令
    php中的json_decode
    有用的sql积累
    git submodule使用原理
    mysql重复插入时insert更改为update更新操作
    jpm
    awk 语句
    tomcat 发布简单的html网站
  • 原文地址:https://www.cnblogs.com/kuronekonano/p/11135793.html
Copyright © 2020-2023  润新知