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新加数据一组,2016.7.9放至40S,600M,但未重测

    Source

    by zhzqkkk

    Solution

    三维偏序。可以看做位置在一个区间内,上一个在区间外,下一个也在区间外的的数的最大值。我们发现有一维是前缀(上一个出现的位置)所以这一维就可以可持久化,剩下两维就树套树咯。。。复杂度O(nlog^2)

    Code

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <algorithm>
      4 
      5 #define R register
      6 #define maxn 100010
      7 #define dmax(_a, _b) ((_a) > (_b) ? (_a) : (_b))
      8 #define cmax(_a, _b) (_a < (_b) ? _a = (_b) : 0)
      9 
     10 inline int F()
     11 {
     12     R int cnt = 0; R char ch;
     13     while (ch = getchar(), ch < '0' || ch > '9') ;
     14     cnt = ch - '0';
     15     while (ch = getchar(), ch >= '0' && ch <= '9') cnt = cnt * 10 + ch - '0';
     16     return cnt;
     17 }
     18 int next[maxn], prev[maxn], last[maxn], r[maxn], n, a[maxn];
     19 inline bool cmp(R int a, R int b) { return prev[a] < prev[b];}
     20 struct Seg2 {
     21     Seg2 *ls, *rs;
     22     int mx;
     23 } mem2[maxn * 450], *tot2 = mem2;
     24 struct Seg1 {
     25     Seg1 *ls, *rs;
     26     Seg2 *x;
     27 } *rt[maxn], mem1[maxn * 30], *tot1 = mem1;
     28 Seg2 *insert2(R Seg2 *lst, R int l, R int r, R int x, R int v)
     29 {
     30     R Seg2 *now = ++tot2;
     31     now -> mx = dmax(lst -> mx, v);
     32     if (l == r) return now;
     33     R int mid = l + r >> 1;
     34     if (x <= mid)
     35     {
     36         now -> rs = lst -> rs;
     37         now -> ls = insert2(lst -> ls, l, mid, x, v);
     38     }
     39     else
     40     {
     41         now -> ls = lst -> ls;
     42         now -> rs = insert2(lst -> rs, mid + 1, r, x, v);
     43     }
     44     return now;
     45 }
     46 Seg1 *insert1(R Seg1 *lst, R int l, R int r, R int x)
     47 {
     48     R Seg1 *now = ++tot1;
     49     now -> x = insert2(lst -> x, 1, n + 1, next[x], a[x]);
     50     if (l == r) return now;
     51     R int mid = l + r >> 1;
     52     if (x <= mid)
     53     {
     54         now -> rs = lst -> rs;
     55         now -> ls = insert1(lst -> ls, l, mid, x);
     56     }
     57     else
     58     {
     59         now -> ls = lst -> ls;
     60         now -> rs = insert1(lst -> rs, mid + 1, r, x);
     61     }
     62     return now;
     63 }
     64 int query2(R Seg2 *now, R int l, R int r, R int x)
     65 {
     66     if (l == r || now == mem2) return now -> mx;
     67     R int mid = l + r >> 1, ret = 0, tmp;
     68     if (x <= mid)
     69     {
     70         cmax(ret, now -> rs -> mx);
     71         tmp = query2(now -> ls, l, mid, x);
     72         cmax(ret, tmp);
     73     }
     74     else
     75     {
     76         tmp = query2(now -> rs, mid + 1, r, x);
     77         cmax(ret, tmp);
     78     }
     79     return ret;
     80 }
     81 int query1(R Seg1 *now, R int l, R int r, R int ql, R int qr)
     82 {
     83     if (ql <= l && r <= qr) return query2(now -> x, 1, n + 1, qr + 1);
     84     R int mid = l + r >> 1, tmp, ret = 0;
     85     if (ql <= mid) tmp = query1(now -> ls, l, mid, ql, qr), cmax(ret, tmp);
     86     if (mid < qr) tmp = query1(now -> rs, mid + 1, r, ql, qr), cmax(ret, tmp);
     87     return ret;
     88 }
     89 int main()
     90 {
     91     R int m; n = F(); m = F();
     92     mem1 -> ls = mem1 -> rs = mem1; mem1 -> x = mem2;
     93     mem2 -> ls = mem2 -> rs = mem2;
     94     for (R int i = 1; i <= n; ++i)
     95     {
     96         a[i] = F();
     97         r[i] = i;
     98         prev[i] = last[a[i]];
     99         next[last[a[i]]] = i;
    100         last[a[i]] = i;
    101     }
    102     for (R int i = 1; i <= n; ++i) last[i] ? next[last[i]] = n + 1 : 0;
    103     std::sort(r + 1, r + n + 1, cmp);
    104     rt[0] = mem1;
    105     for (R int i = 1; i <= n; ++i)
    106     {
    107         R int now = r[i];
    108         if (prev[now] == 0) rt[0] = insert1(rt[0], 0, n, now);
    109         else rt[prev[now]] = insert1(rt[prev[r[i - 1]]], 0, n, now);
    110     }
    111     for (R int i = 1; i <= n; ++i) if (!rt[i]) rt[i] = rt[i - 1];
    112     R int ans = 0;
    113     for (R int i = 1; i <= m; ++i)
    114     {
    115         R int l = F(), r = F();
    116         (l += ans) %= n; (r += ans) %= n;
    117         l > r ? std::swap(l, r), 1 : 0; ++l; ++r;
    118 //        printf("l = %d r = %d
    ", l, r);
    119         printf("%d
    ", ans = query1(rt[l - 1], 0, n, l, r));
    120     }
    121     return 0;
    122 } 
  • 相关阅读:
    POJ1149 最大流经典建图PIG
    POJ1149 最大流经典建图PIG
    POJ3322滚箱子游戏(不错)
    POJ3322滚箱子游戏(不错)
    UVA11020 优势人群(multiset)
    UVA11020 优势人群(multiset)
    UVA11019KMP(二维矩阵匹配出现次数)
    UVA11019KMP(二维矩阵匹配出现次数)
    LA3942字典树+递推
    LA3942字典树+递推
  • 原文地址:https://www.cnblogs.com/cocottt/p/6780676.html
Copyright © 2011-2022 走看看