zoukankan      html  css  js  c++  java
  • 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,但未重测

    正解:$kd-tree$。

    其实这题正解应该是主席树套什么鬼东西,然而我不会,于是还是上清新的$kd-tree$。。

    我们求出每个点,上一个与它相同的点的位置$lst[i]$,下一个与它相同的点的位置$nxt[i]$。

    那么很容易发现,我们要满足$3$个条件,即$l<=i<=r,lst[i]<l,r<nxt[i]$。

    那么我们直接构造一个以$i,lst[i],nxt[i]$为坐标的点的三维$kd-tree$,查询的时候判断一下就行了。

      1 //It is made by wfj_2048~
      2 #include <algorithm>
      3 #include <iostream>
      4 #include <cstring>
      5 #include <cstdlib>
      6 #include <cstdio>
      7 #include <vector>
      8 #include <cmath>
      9 #include <queue>
     10 #include <stack>
     11 #include <map>
     12 #include <set>
     13 #define inf (1<<30)
     14 #define N (200010)
     15 #define il inline
     16 #define RG register
     17 #define ll long long
     18 #define fi02() for (RG int i=0;i<=2;++i)
     19 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
     20 
     21 using namespace std;
     22 
     23 int pos[N],lst[N],nxt[N],a[N],K,n,m,l,r,rt,ans;
     24 
     25 struct node{
     26     int a[3],mn[3],mx[3],l,r,v,sum;
     27 
     28     bool operator < (const node &t) const{
     29     return a[K]<t.a[K];
     30     }
     31     
     32 }t[N];
     33 
     34 il int gi(){
     35     RG int x=0,q=1; RG char ch=getchar();
     36     while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
     37     if (ch=='-') q=-1,ch=getchar();
     38     while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar();
     39     return q*x;
     40 }
     41 
     42 il void merge(RG int x){
     43     fi02(){
     44     if (t[x].l){
     45         t[x].mn[i]=min(t[x].mn[i],t[t[x].l].mn[i]);
     46         t[x].mx[i]=max(t[x].mx[i],t[t[x].l].mx[i]);
     47     }
     48     if (t[x].r){
     49         t[x].mn[i]=min(t[x].mn[i],t[t[x].r].mn[i]);
     50         t[x].mx[i]=max(t[x].mx[i],t[t[x].r].mx[i]);
     51     }
     52     }
     53     t[x].sum=max(t[t[x].l].sum,t[t[x].r].sum);
     54     t[x].sum=max(t[x].sum,t[x].v); return;
     55 }
     56 
     57 il int build(RG int l,RG int r,RG int p){
     58     RG int mid=(l+r)>>1; K=p,nth_element(t+l,t+mid,t+r+1);
     59     fi02() t[mid].mn[i]=t[mid].mx[i]=t[mid].a[i];
     60     if (l<mid) t[mid].l=build(l,mid-1,(p+1)%3);
     61     if (r>mid) t[mid].r=build(mid+1,r,(p+1)%3);
     62     merge(mid); return mid;
     63 }
     64 
     65 il int ca(node S){ return l<=S.mn[0] && S.mx[0]<=r && S.mx[1]<l && S.mn[2]>r; }
     66 
     67 il int cb(node S){
     68     if (S.mn[1]>=l) return 0; if (S.mx[2]<=r) return 0;
     69     if (S.mn[0]>r || S.mx[0]<l) return 0; return 1;
     70 }
     71 
     72 il void query(RG int x){
     73     if (l<=t[x].a[0] && t[x].a[0]<=r && t[x].a[1]<l && t[x].a[2]>r) ans=max(ans,t[x].v);
     74     if (t[t[x].l].sum>t[t[x].r].sum){
     75     if (t[x].l){
     76         if (ca(t[t[x].l])) ans=max(ans,t[t[x].l].sum);
     77         else if (cb(t[t[x].l]) && ans<t[t[x].l].sum) query(t[x].l);
     78     }
     79     if (t[x].r){
     80         if (ca(t[t[x].r])) ans=max(ans,t[t[x].r].sum);
     81         else if (cb(t[t[x].r]) && ans<t[t[x].r].sum) query(t[x].r);
     82     }
     83     } else{
     84     if (t[x].r){
     85         if (ca(t[t[x].r])) ans=max(ans,t[t[x].r].sum);
     86         else if (cb(t[t[x].r]) && ans<t[t[x].r].sum) query(t[x].r);
     87     }
     88     if (t[x].l){
     89         if (ca(t[t[x].l])) ans=max(ans,t[t[x].l].sum);
     90         else if (cb(t[t[x].l]) && ans<t[t[x].l].sum) query(t[x].l);
     91     }
     92     }
     93     return;
     94 }
     95 
     96 il void work(){
     97     n=gi(),m=gi();
     98     for (RG int i=1;i<=n;++i){
     99     a[i]=gi(),lst[i]=pos[a[i]];
    100     nxt[pos[a[i]]]=i,pos[a[i]]=i;
    101     }
    102     for (RG int i=1;i<=n;++i){
    103     if (!nxt[i]) nxt[i]=n+1; t[i].sum=t[i].v=a[i];
    104     t[i].a[0]=i,t[i].a[1]=lst[i],t[i].a[2]=nxt[i];
    105     }
    106     rt=build(1,n,0);
    107     while (m--){
    108     l=(gi()+ans)%n+1,r=(gi()+ans)%n+1,ans=0;
    109     if (l>r) swap(l,r); query(rt),printf("%d
    ",ans);
    110     }
    111     return;
    112 }
    113 
    114 int main(){
    115     File("rmq");
    116     work();
    117     return 0;
    118 }
  • 相关阅读:
    Python之标示符和关键字
    Python之变量以及类型
    python之注释的分类
    Python的环境的搭建
    Python之第一个helloworld的代码
    Linux_ubuntu-命令系统管理
    Linux_ubuntu命令-用户、权限管理
    Linux-ubuntu命令-文件、磁盘管理
    Linux_Ubuntu命令概述
    Linux-Ubuntu文件权限
  • 原文地址:https://www.cnblogs.com/wfj2048/p/6951751.html
Copyright © 2011-2022 走看看