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

    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的第二行最后多了个空格。

    2015.6.24新加数据一组,但未重测

    Source

    by zhzqkkk

     正解:kd-tree

    解题报告:

      做这道题本来是为了试试可持久化线段树的,然而感觉好复杂。结果在网上突然看到一份博客,居然用的是kd-tree,当时就激动了。

      参考博客:http://trinklee.blog.163.com/blog/static/2381580602015422933539/

      这份博客讲的很清楚了,三维kd-tree。我们维护三个值,当前值的上一次出现位置,下一次出现位置。显然查询区间[l,r]时i满足当且仅当 last[num[i]]<l && next[num[i]]>r 时才需被计入贡献,满足要求。

      那么这样的查询显然是可以用kd-tree来做的。都是老套路了,想好怎么建了就跟我之前做的两道kd-tree题一样了。还没有插入操作了,还简单些了好吗

      代码如下:

      1 //It is made by jump~
      2 #include <iostream>
      3 #include <cstdlib>
      4 #include <cstring>
      5 #include <cstdio>
      6 #include <cmath>
      7 #include <algorithm>
      8 #include <ctime>
      9 #include <vector>
     10 #include <queue>
     11 #include <map>
     12 #include <set>
     13 #ifdef WIN32   
     14 #define OT "%I64d"
     15 #else
     16 #define OT "%lld"
     17 #endif
     18 using namespace std;
     19 typedef long long LL;
     20 const int MAXN = 100011;
     21 int shu[MAXN];
     22 int n,m;
     23 int last[MAXN];
     24 int L[MAXN],R[MAXN];
     25 int root;
     26 int D;
     27 int ans;
     28 int cha[3][2];
     29 
     30 struct node{
     31     int l,r;
     32     int Min[3],Max[3],d[3];
     33     int num;
     34     int zhi;
     35 }a[MAXN];
     36 
     37 inline int getint()
     38 {
     39        int w=0,q=0;
     40        char c=getchar();
     41        while((c<'0' || c>'9') && c!='-') c=getchar();
     42        if (c=='-')  q=1, c=getchar();
     43        while (c>='0' && c<='9') w=w*10+c-'0', c=getchar();
     44        return q ? -w : w;
     45 }
     46 
     47 inline bool cmp(node q,node qq){
     48     for(int i=0;i<=2;i++)
     49     if(q.d[(D+i)%3]!=qq.d[(D+i)%3]) return (q.d[(D+i)%3]<qq.d[(i+D)%3]);
     50     return 1;
     51 }
     52 
     53 inline void update(int x){
     54     if(a[x].l) {
     55     for(int i=0;i<=2;i++) a[x].Min[i]=min(a[x].Min[i],a[a[x].l].Min[i]),a[x].Max[i]=max(a[x].Max[i],a[a[x].l].Max[i]);
     56     a[x].zhi=max(a[x].zhi,a[a[x].l].zhi);
     57     }
     58     if(a[x].r) {
     59     for(int i=0;i<=2;i++) a[x].Min[i]=min(a[x].Min[i],a[a[x].r].Min[i]),a[x].Max[i]=max(a[x].Max[i],a[a[x].r].Max[i]);
     60     a[x].zhi=max(a[x].zhi,a[a[x].r].zhi);
     61     }
     62 }
     63 
     64 inline int build_tree(int l,int r,int d){
     65     int mid=(l+r)/2; D=d;
     66     nth_element(a+l+1,a+mid+1,a+r+1,cmp);
     67     a[mid].zhi=a[mid].num;
     68     for(int i=0;i<=2;i++) a[mid].Min[i]=a[mid].Max[i]=a[mid].d[i];
     69 
     70     if(l!=mid) a[mid].l=build_tree(l,mid-1,(d+1)%3);
     71     if(mid!=r) a[mid].r=build_tree(mid+1,r,(d+1)%3);
     72     update(mid);
     73     return mid;
     74 }
     75 
     76 inline bool pan(int now){
     77     for(int i=0;i<=2;i++) {
     78     if(a[now].Max[i]<cha[i][0] || a[now].Min[i]>cha[i][1]) return false;
     79     }
     80     return true;
     81 }
     82 
     83 inline void query(int now) {
     84     if(a[now].zhi<ans) return ;//剪枝
     85     bool flag=true;
     86     for(int i=0;i<=2;i++) if(cha[i][0]>a[now].Min[i] || cha[i][1]<a[now].Max[i] ) { flag=false; break;}
     87     if(flag) { ans=max(ans,a[now].zhi); return ; }
     88     flag=true;
     89 
     90     for(int i=0;i<=2;i++) if(cha[i][0]>a[now].d[i] || cha[i][1]<a[now].d[i]) flag=false;
     91     if(flag) { ans=max(ans,a[now].num); }
     92     if(a[now].l && pan(a[now].l)) { query(a[now].l); }
     93     if(a[now].r && pan(a[now].r)) { query(a[now].r); }
     94 }
     95 
     96 inline void solve(){
     97     n=getint(); m=getint();
     98 
     99     for(int i=1;i<=n;i++) {
    100     shu[i]=getint();
    101     L[i]=last[shu[i]];
    102     last[shu[i]]=i;
    103     }
    104 
    105     for(int i=1;i<=n;i++) last[i]=n+1;
    106 
    107     for(int i=n;i>=1;i--) R[i]=last[shu[i]],last[shu[i]]=i;
    108 
    109     for(int i=1;i<=n;i++) {
    110     a[i].d[0]=i; a[i].d[1]=L[i]; a[i].d[2]=R[i];
    111     a[i].num=shu[i];
    112     }
    113 
    114     root=build_tree(1,n,0);
    115 
    116     int l,r,x,y;
    117     for(int i=1;i<=m;i++) {
    118     l=getint(); r=getint();
    119     x=(l+ans)%n+1; y=(r+ans)%n+1;
    120     if(x<y) l=x,r=y;
    121     else l=y,r=x;
    122 
    123     ans=0;
    124     cha[0][0]=l; cha[0][1]=r;
    125     cha[1][0]=0; cha[1][1]=l-1;
    126     cha[2][0]=r+1; cha[2][1]=n+1;
    127     query(root);
    128     printf("%d
    ",ans);
    129     }
    130 }
    131 
    132 int main()
    133 {
    134   solve();
    135   return 0;
    136 }
  • 相关阅读:
    如何将网格式报表打印成其它样式
    拥有与实力不相称的脾气是种灾难——北漂18年(23)
    8.8.1 Optimizing Queries with EXPLAIN
    mysql 没有rowid 怎么实现根据rowid回表呢?
    secondary index
    8.5.5 Bulk Data Loading for InnoDB Tables 批量数据加载
    mysql 中key 指的是索引
    8.5.4 Optimizing InnoDB Redo Logging 优化InnoDB Redo 日志
    8.5.3 Optimizing InnoDB Read-Only Transactions 优化InnoDB 只读事务
    8.5.1 Optimizing Storage Layout for InnoDB Tables InnoDB表的存储布局优化
  • 原文地址:https://www.cnblogs.com/ljh2000-jump/p/5595239.html
Copyright © 2011-2022 走看看