zoukankan      html  css  js  c++  java
  • [BZOJ3489] A simple rmq problem

    [BZOJ3489] A simple rmq problem

    Description

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

    Input

    第一行为两个整数N,M。M是询问数,N是序列的长度(N<=100000,M<=200000)
    第二行为N个整数,描述这个序列{ai},其中所有1<=ai<=N
    再下面M行,每行两个整数x,y,询问区间[l,r]由下列规则产生(OIER都知道是怎样的吧>_<):l=min((x+lastans)mod n+1,(y+lastans)mod n+1);r=max((x+lastans)mod n+1,(y+lastans)mod n+1);Lastans表示上一个询问的答案,一开始lastans为0

    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的第二行最后多了个空格。2015.6.24新加数据一组,2016.7.9放至40S,600M,但未重测

    试题分析

    遇到出现次数的题,首先应该想到一种套路叫做维护pre和nxt。
    那么这道题建立3维(pre,nxt,pos)的kd-tree后就简单了。

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<vector>
    #include<algorithm>
     
    using namespace std;
    #define LL long long
     
    inline int read(){
        int x=0,f=1;char c=getchar();
        for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
        for(;isdigit(c);c=getchar()) x=x*10+c-'0';
        return x*f;
    }
    const int INF = 2147483600;
    const int MAXN = 310000;
     
    struct data{int mx[3],mn[3]; int d[3],val,Mx;}a[MAXN+1],b[MAXN+1];
    int D,N,M; int nxt[MAXN+1],vis[MAXN+1],pre[MAXN+1];
    int ls[MAXN+1],rs[MAXN+1]; int c[MAXN+1],d[MAXN+1];
     
    inline void update(int k,int x){
        a[k].Mx=max(a[k].Mx,a[x].Mx);
        for(int i=0;i<3;i++){
            a[k].mx[i]=max(a[k].mx[i],a[x].mx[i]);
            a[k].mn[i]=min(a[k].mn[i],a[x].mn[i]);
        } return ;
    } 
    inline bool cmp(data a,data b){return a.d[D]<b.d[D];}
    inline int build(int l,int r,int d){
        D=d; int mid=(l+r)>>1;
        nth_element(b+l,b+mid,b+r+1,cmp); a[mid]=b[mid]; a[mid].Mx=a[mid].val;
        for(int i=0;i<3;i++) a[mid].mx[i]=a[mid].mn[i]=a[mid].d[i];
        if(l<mid) ls[mid]=build(l,mid-1,(d+1)%3);
        if(r>mid) rs[mid]=build(mid+1,r,(d+1)%3);
        if(ls[mid]) update(mid,ls[mid]);
        if(rs[mid]) update(mid,rs[mid]);
        //cout<<mid<<":"<<a[mid].val<<" "<<a[mid].Mx<<" "<<ls[mid]<<" "<<rs[mid]<<endl;
        return mid;
    } int lastans;
    inline bool isquare(int rt,int l,int r){
        return l<=a[rt].mn[0]&&a[rt].mn[0]<=r&&l<=a[rt].mx[0]&&a[rt].mx[0]<=r&&a[rt].mx[1]<l&&a[rt].mn[1]<l&&a[rt].mn[2]>r&&a[rt].mx[2]>r;
    }
    inline bool inpoint(int rt,int l,int r){
        return l<=a[rt].d[0]&&a[rt].d[0]<=r&&a[rt].d[1]<l&&a[rt].d[2]>r;
    }
    inline void Query(int rt,int l,int r){
        if(a[rt].Mx<lastans||!rt) return ; //cout<<rt<<":"<<a[rt].d[0]<<" "<<a[rt].d[1]<<" "<<a[rt].Mx<<":"<<l<<" "<<r<<endl;
        if(a[rt].mn[0]>r||a[rt].mx[0]<l||a[rt].mn[1]>=l||a[rt].mx[2]<=r) return ;
        if(isquare(rt,l,r)) {lastans=max(lastans,a[rt].Mx); return ;}
        if(inpoint(rt,l,r)) lastans=max(lastans,a[rt].val); 
        if(a[ls[rt]].Mx>=a[rs[rt]].Mx){
            if(ls[rt]) Query(ls[rt],l,r);
            if(rs[rt]) Query(rs[rt],l,r);
        }
        else{
            if(rs[rt]) Query(rs[rt],l,r);
            if(ls[rt]) Query(ls[rt],l,r);
        } return ;
    }
     
    int main(){
        //freopen(".in","r",stdin);
        //freopen(".out","w",stdout);
        N=read(),M=read();
        for(int i=1;i<=N;i++) c[i]=d[i]=read(); sort(c+1,c+N+1);
        for(int i=1;i<=N;i++) b[i].val=d[i];
        for(int i=1;i<=N;i++) d[i]=lower_bound(c+1,c+N+1,d[i])-c;
        for(int i=1;i<=N;i++){
            nxt[vis[d[i]]]=i;
            pre[i]=vis[d[i]];
            vis[d[i]]=i;
        } for(int i=1;i<=N;i++) if(vis[i]) nxt[vis[i]]=N+1;
        for(int i=1;i<=N;i++) b[i].d[1]=pre[i],b[i].d[2]=nxt[i],b[i].d[0]=i;
        int root=build(1,N,0);
        while(M--){
            int l=(read()+lastans)%N+1,r=(read()+lastans)%N+1;
            if(l>r) swap(l,r);
            //cout<<l<<" "<<r<<endl; 
            lastans=0; Query(root,l,r); printf("%d
    ",lastans);
        }
        return 0;
    }
    
    
  • 相关阅读:
    Security and Cryptography in Python
    Security and Cryptography in Python
    Security and Cryptography in Python
    Security and Cryptography in Python
    Security and Cryptography in Python
    Security and Cryptography in Python
    基于分布式锁解决定时任务重复问题
    基于Redis的Setnx实现分布式锁
    基于数据库悲观锁的分布式锁
    使用锁解决电商中的超卖
  • 原文地址:https://www.cnblogs.com/wxjor/p/9529048.html
Copyright © 2011-2022 走看看