zoukankan      html  css  js  c++  java
  • bzoj 3489: A simple rmq problem k-d树思想大暴力

    3489: A simple rmq problem

    Time Limit: 10 Sec  Memory Limit: 512 MB
    Submit: 551  Solved: 170
    [Submit][Status][Discuss]

    Description

    因为是OJ上的题,就简单点好了。给出一个长度为n的序列,给出M个询问:在[l,r]之间找到一个在这个区间里只出现过一次的数,并且要求找的这个数尽可能大。如果找不到这样的数,则直接输出0。我会采取一些措施强制在线。

     

     

    Input

    第一行为两个整数N,MM是询问数,N是序列的长度(N<=100000M<=200000)

    第二行为N个整数,描述这个序列{ai},其中所有1<=ai<=N

    再下面M行,每行两个整数xy

    询问区间[l,r]由下列规则产生(OIER都知道是怎样的吧>_<)

    l=min(x+lastans)mod n+1,(y+lastansmod n+1);

    r=max(x+lastans)mod n+1,(y+lastansmod n+1);

    Lastans表示上一个询问的答案,一开始lastans0

     

    Output

    一共M行,每行给出每个询问的答案。

     

    Sample Input

    10 10
    6 4 9 10 9 10 9 4 10 4
    3 8
    10 1
    3 4
    9 4
    8 1
    7 8
    2 9
    1 1
    7 3
    9 9

    Sample Output

    4
    10
    10
    0
    0
    10
    0
    4
    0
    4

    HINT



    注意出题人为了方便,input的第二行最后多了个空格。

      曾经以为这是自己一道原创题啊,直到在bzoj发现了这道题。。。

      某日学姐问了一道这个问题的离线版,然后说正解是裸裸的O(nlogn)线段树,然后就都不会了,O(nlogn)的解法我还是怀疑不存在的,不过线段树套set到是没啥问题的。

      然后另一日,hja表示这道题可以出成在线版,问数据范围,n=3*10^5.

      于是乎hja自己的程序被卡mle了,然而本人蒟蒻,更本不想写主席树套可持久化Treap,于是乎yy出了这个O(n^2)算法。

      考虑离线询问,按照r排序,对于每一个权值,我们在线段树的对应位置存下它有贡献的区间(即prv[prv[x]]+1到prv[x])对于一个权值区间,我们存下所有权值所对应的贡献区间的L-min和R-max。对于R确定的询问(L,R)我们只需要在线段树上找到最大的权值,使其区间包含L,于是我们优先递归权值大的一边,找到及退出,如果当前权值区间的(L-min,R-max)已经不可能包含L值了,那么也直接退出,这个和k-d树的find机制非常像。

      离线我们只需要一个线段树,那么在线的话把线段树换成主席树就ok啦。

      发现bzoj数据范围只有10^5,一交rank2!!!!加上读入优化1960ms的rank1!!!!

      爽。。。。暴力虐标程。。。。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define MAXN 100100
    #define MAXT MAXN*25
    #define INF 0x3f3f3f3f
    #define smid ((l+r)>>1)
    inline int nextInt()
    {
            register char ch;
            register int x=0;
            while (ch=getchar(),ch<'0' || ch>'9');
            while (x=x*10+ch-'0',ch=getchar(),ch<='9' && ch>='0');
            return x;
    }
    struct sgt_node
    {
            int lc,rc;
            int mn,mx;
            sgt_node()
            {
                    mn=INF;
                    mx=-INF;
            }
    }sgt[MAXT];
    int topt=0;
    int Modify_sgt(int now,int l,int r,int pos,int v1,int v2)
    {
            sgt[++topt]=sgt[now];
            now=topt;
            if (l==r)
            {
                    sgt[now].mn=v1;
                    sgt[now].mx=v2;
                    return now;
            }
            if (pos<=smid)
                    sgt[now].lc=Modify_sgt(sgt[now].lc,l,smid,pos,v1,v2);
            else
                sgt[now].rc=Modify_sgt(sgt[now].rc,smid+1,r,pos,v1,v2);
            sgt[now].mn=min(sgt[sgt[now].lc].mn,sgt[sgt[now].rc].mn);
            sgt[now].mx=max(sgt[sgt[now].lc].mx,sgt[sgt[now].rc].mx);
            return now;
    }
    int Query_sgt(int now,int l,int r,int v)
    {
            if (l==r)
                    return v<=sgt[now].mx && v>=sgt[now].mn?l:0;
            int ret=0;
            if (sgt[sgt[now].rc].mn<=v && sgt[sgt[now].rc].mx>=v)
            {
                    ret=Query_sgt(sgt[now].rc,smid+1,r,v);
                    if (ret)return ret;
            }
            return Query_sgt(sgt[now].lc,l,smid,v);
    }
    int a[MAXN];
    int tmp[MAXN];
    int prv[MAXN];
    int root[MAXN];
    
    int main()
    {
            //freopen("seq0.in","r",stdin);
            //freopen("seq10.out","w",stdout);
            freopen("input.txt","r",stdin);
            //freopen("output.txt","w",stdout);
            int n,m,x,y,z;
            n=nextInt(),m=nextInt();
            for (int i=1;i<=n;i++)
                    a[i]=nextInt();
            for (int i=1;i<=n;i++)
            {
                    prv[i]=tmp[a[i]];
                    tmp[a[i]]=i;
            }
            for (int i=1;i<=n;i++)
                    root[i]=Modify_sgt(root[i-1],0,n,a[i],prv[i]+1,i);
            int lastans=0;
            int aa,bb;
            for (int i=0;i<m;i++)
            {
                    aa=nextInt(),bb=nextInt();
                    x=min((aa+lastans)%n+1,(bb+lastans)%n+1);
                    y=max((aa+lastans)%n+1,(bb+lastans)%n+1);
                    printf("%d
    ",lastans=Query_sgt(root[y],0,n,x));
            }
    }
  • 相关阅读:
    Remote desktop manager共享账号
    content is not supported outside 'script" or asp content' region
    How to pass values across the pages in ASP.net without using Session
    GitLab Flow
    C#如何获取系统downloads和documents路径
    sql server查询结果复制出来,没有换行(存进去的数据是换行的)
    Type Interceptors
    JsonNode、JsonObject常用方法
    java获取当前时间戳的方法
    Java中float/double取值范围与精度
  • 原文地址:https://www.cnblogs.com/mhy12345/p/4517347.html
Copyright © 2011-2022 走看看