zoukankan      html  css  js  c++  java
  • BZOJ 3489: A simple rmq problem KDtree

    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行,每行给出每个询问的答案。

     题解: 对于一个区间 $[l,r]$ 一个数只出现依次说明上次出现在 $[1,l-1]$ 中(或没出现),下一次出现在 $[r+1,n]$ 中(或没出现).
    直接维护一个 3 维 $KDtree$ 即可.
    第一维维护 $pre_{i}$,第二位维护 $i$ 本身,第三维维护下一次出现的位置.
    每次按照上述条件直接进行数点即可.
    思路还是非常巧妙的.  

    #include<bits/stdc++.h>
    #define maxn 200000 
    #define inf 100000000
    #define mid ((l+r)>>1)
    #define lson (t[x].ch[0])
    #define rson (t[x].ch[1])  
    using namespace std;
    void setIO(string s)
    {
        string in=s+".in"; 
        freopen(in.c_str(),"r",stdin);  
    }
    int n,Q,lastans,d,_ans; 
    int lst[maxn],nex[maxn],pos[maxn],arr[maxn];    
    struct Node
    {
        int ch[2],minv[3],maxv[3],p[3],w,_max; 
    }t[maxn]; 
    bool cmp(Node a,Node b)
    {
        if(a.p[d]==b.p[d] && a.p[(d+1)%3]==b.p[(d+1)%3]) return a.p[(d+2)%3] < b.p[(d+2)%3]; 
        if(a.p[d]==b.p[d]) return a.p[(d+1)%3] < b.p[(d+1)%3]; 
        return a.p[d] < b.p[d];    
    }
    void pushup(int x,int y)
    {
        for(int i=0;i<3;++i) 
        {
            t[x].minv[i]=min(t[x].minv[i],t[y].minv[i]); 
            t[x].maxv[i]=max(t[x].maxv[i],t[y].maxv[i]);   
        }
        t[x]._max=max(t[x]._max,t[y]._max);        
    }
    int build(int l,int r,int o)
    {
        d=o;   
        nth_element(t+l,t+mid,t+1+r,cmp); 
        for(int i=0;i<3;++i) t[mid].minv[i]=t[mid].maxv[i]=t[mid].p[i];       
        t[mid].ch[0]=t[mid].ch[1]=0; 
        t[mid]._max=t[mid].w;    
        if(mid>l)
        {
            t[mid].ch[0]=build(l,mid-1,(o+1)%3); 
            pushup(mid,t[mid].ch[0]); 
        }
        if(r>mid) 
        {
            t[mid].ch[1]=build(mid+1,r,(o+1)%3); 
            pushup(mid,t[mid].ch[1]); 
        }
        return mid; 
    }
    int isout(int x,int l,int r)
    {
        if(t[x].minv[0] >= l || t[x].maxv[2] <= r || t[x].minv[1] > r || t[x].maxv[1] < l) return 1; 
        return 0; 
    }
    int isin(int x,int l,int r)
    {
        if(t[x].maxv[0] < l && t[x].minv[2] > r && t[x].minv[1] >= l && t[x].maxv[1] <= r) return 1; 
        return 0; 
    }
    void query(int x,int l,int r)
    {
        if(isout(x, l, r)) return; 
        if(isin(x, l, r)) 
        {
            _ans=max(_ans, t[x]._max); 
            return; 
        } 
        if(t[x].p[0] < l && t[x].p[1] >= l && t[x].p[1] <= r && t[x].p[2] > r) _ans=max(_ans, t[x].w); 
        if(lson && t[lson]._max > _ans) query(lson, l, r);  
        if(rson && t[rson]._max > _ans) query(rson, l, r); 
    }
    int main()
    {
        int i,j,x,y,root,a; 
        // setIO("input"); 
        scanf("%d%d",&n,&Q); 
        for(i=1;i<=n;++i)  
        {
            scanf("%d",&a);  
            nex[pos[a]]=i, lst[i]=pos[a], pos[a]=i, arr[i]=a; 
        } 
        for(i=1;i<=n;++i)
        {
            t[i].p[0]=lst[i], t[i].p[1]=i, t[i].p[2] = nex[i] ? nex[i] : n + 1, t[i].w=arr[i];  
        }
        root=build(1,n,0); 
        while(Q--)
        {
            scanf("%d%d",&x,&y); 
            x=(x+lastans) % n + 1; 
            y=(y+lastans) % n + 1; 
            if(x > y) swap(x, y); 
            _ans = -inf; 
            query(root, x, y); 
            lastans = (_ans == -inf ? 0 : _ans); 
            printf("%d
    ",lastans); 
        }
        return 0; 
    }
    

      

  • 相关阅读:
    ✨Synchronized底层实现---偏向锁
    🌞LCP 13. 寻宝
    ✨Synchronized底层实现---概述
    ⛅104. 二叉树的最大深度
    c++多线程之顺序调用类成员函数
    C++ STL实现总结
    C#小知识
    C#中HashTable和Dictionary的区别
    WPF的静态资源(StaticResource)和动态资源(DynamicResource)
    WPF之再谈MVVM
  • 原文地址:https://www.cnblogs.com/guangheli/p/11060643.html
Copyright © 2011-2022 走看看