• BZOJ 3489: A simple rmq problem


    3489: A simple rmq problem

    Time Limit: 40 Sec  Memory Limit: 600 MB
    Submit: 1594  Solved: 520
    [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的第二行最后多了个空格。


    2015.6.24新加数据一组,2016.7.9放至40S,600M,但未重测


    Source

    [Submit][Status][Discuss]

    参考了网上的一些做法,可持久化树套树什么的实在吃不消,于是采用了KD-Tree的方法。

    考虑一个点,在哪个区间内它是唯一出现的呢?

    设prev[i]为上一个和i处权值相同的位置,next[i]为下一个和i处权值相同的位置,显然在(prev[i],next[i])这个区间内,i点是该权值唯一出现的位置。

    对于一个询问(ql,qr),我们可以转换为:找出满足 prev[i] < ql 且 next[i] > qr 且 ql <= i <= qr 的i中,权值最大的i。这个就是KD-Tree维护三维的区间最值问题。

      1 #include <bits/stdc++.h>
      2 
      3 inline int getC(void) {
      4     static const int siz = 1024;
      5     
      6     static char buf[siz];
      7     static char *hd = buf + siz;
      8     static char *tl = buf + siz;
      9     
     10     if (hd == tl)
     11         fread(hd = buf, 1, siz, stdin);
     12     
     13     return int(*hd++);
     14 }
     15 
     16 inline int getI(void) {
     17     register int ret = 0;
     18     register int neg = false;
     19     register int bit = getC();
     20     
     21     for (; bit < 48; bit = getC())
     22         if (bit == '-')neg ^= true;
     23 
     24     for (; bit > 47; bit = getC())
     25         ret = ret * 10 + bit - '0';
     26     
     27     return neg ? -ret : ret;
     28 }
     29 
     30 template <class T>
     31 inline T min(const T &a, const T &b) {
     32     return a < b ? a : b;
     33 }
     34 
     35 template <class T>
     36 inline T max(const T &a, const T &b) {
     37     return a > b ? a : b;
     38 }
     39 
     40 const int maxn = 100005;
     41 
     42 int n, m;
     43 int answer;
     44 int num[maxn];
     45 
     46 int next[maxn];
     47 int prev[maxn];
     48 int last[maxn];
     49 
     50 int value[maxn][3];
     51 
     52 int pos[maxn];
     53 int maxv[maxn];
     54 int lson[maxn];
     55 int rson[maxn];
     56 int mini[maxn][3];
     57 int maxi[maxn][3];
     58 
     59 int qryL, qryR;
     60 
     61 int cmpK;
     62 
     63 inline bool cmp(const int &a, const int &b) {
     64     return value[a][cmpK] < value[b][cmpK];
     65 }
     66 
     67 int build(int l, int r, int k) {
     68     int mid = (l + r) >> 1; cmpK = k;
     69     std::nth_element(
     70        pos + l, pos + mid, pos + r + 1, cmp);
     71     maxv[mid] = num[pos[mid]];
     72     for (int i = 0; i < 3; ++i)
     73         mini[mid][i] = maxi[mid][i] = value[pos[mid]][i];
     74     if (l < mid) {
     75         lson[mid] = build(l, mid - 1, (k + 1) % 3);
     76         maxv[mid] = max(maxv[mid], maxv[lson[mid]]);
     77         for (int i = 0; i < 3; ++i) {
     78             mini[mid][i] = min(mini[mid][i], mini[lson[mid]][i]);
     79             maxi[mid][i] = max(maxi[mid][i], maxi[lson[mid]][i]);
     80         }
     81     }
     82     if (r > mid) {
     83         rson[mid] = build(mid + 1, r, (k + 1) % 3);
     84         maxv[mid] = max(maxv[mid], maxv[rson[mid]]);
     85         for (int i = 0; i < 3; ++i) {
     86             mini[mid][i] = min(mini[mid][i], mini[rson[mid]][i]);
     87             maxi[mid][i] = max(maxi[mid][i], maxi[rson[mid]][i]);
     88         }
     89     }
     90     return mid;
     91 }
     92 
     93 inline bool check(int t) {
     94     if (mini[t][0] >  qryR || maxi[t][0] <  qryL)return false;
     95     if (mini[t][1] >= qryL || maxi[t][2] <= qryR)return false;
     96     return true;
     97 }
     98 
     99 void query(int t) {
    100     if (mini[t][0] >= qryL && maxi[t][0] <= qryR && maxi[t][1] < qryL && mini[t][2] > qryR)
    101         { answer = max(answer, maxv[t]); return; }
    102     if (pos[t] >= qryL && pos[t] <= qryR && prev[pos[t]] < qryL && next[pos[t]] > qryR)
    103         answer = max(answer, num[pos[t]]);
    104     if (maxv[lson[t]] > maxv[rson[t]]) {
    105         if (lson[t] && maxv[lson[t]] > answer && check(lson[t]))query(lson[t]);
    106         if (rson[t] && maxv[rson[t]] > answer && check(rson[t]))query(rson[t]);
    107     }
    108     else {
    109         if (rson[t] && maxv[rson[t]] > answer && check(rson[t]))query(rson[t]);
    110         if (lson[t] && maxv[lson[t]] > answer && check(lson[t]))query(lson[t]);
    111     }
    112 }
    113 
    114 signed main(void) {
    115     n = getI();
    116     m = getI();
    117     
    118     for (int i = 1; i <= n; ++i)
    119         num[i] = getI();
    120         
    121     for (int i = 1; i <= n; ++i)
    122         last[i] = 0;
    123         
    124     for (int i = 1; i <= n; ++i)
    125         prev[i] = last[num[i]], last[num[i]] = i;
    126         
    127     for (int i = n; i >= 1; --i)
    128         last[i] = n + 1;
    129     
    130     for (int i = n; i >= 1; --i)
    131         next[i] = last[num[i]], last[num[i]] = i;
    132         
    133     for (int i = 1; i <= n; ++i) {
    134         pos[i] = i;
    135         value[i][0] = i;
    136         value[i][1] = prev[i];
    137         value[i][2] = next[i];
    138     }
    139         
    140     int root = build(1, n, 0);
    141     
    142     for (int i = 1; i <= m; ++i) {
    143         int x = getI();
    144         int y = getI();
    145         qryL = (x + answer) % n + 1;
    146         qryR = (y + answer) % n + 1;
    147         if (qryL > qryR)
    148             qryL ^= (qryR ^= (qryL ^= qryR));
    149         answer = 0; query(root); printf("%d
    ", answer);
    150     }
    151 }

    @Author: YouSiki

  • 相关阅读:
    Mapreduce实例——求平均值
    Mapreduce实例——单表join
    《短码之美》读书笔记1
    Mapreduce实例——Map端join使用addCacheFile()方法报错,找不到文件
    Mapreduce实例——Map端join
    C# 异常捕获
    Mapreduce实例——排序
    无名
    数据库设计体会
    oracle 删除表空间错误 提示:ora02429:无法删除用于强制唯一/主键的索引。
  • 原文地址:https://www.cnblogs.com/yousiki/p/6242135.html
Copyright © 2020-2023  润新知