【BZOJ3489】A simple rmq problem

【BZOJ3489】A simple rmq problem

题面

bzoj

题解

这个题不强制在线的话随便做啊。。。

考虑强制在线时怎么搞

预处理出一个位置上一个出现的相同数的位置\(pre\)与下一个位置\(nxt\)

则对于一个询问\([l,r]\)

一个位置\(i\)当且仅当\(pre_i<l\)\(nxt_i>r\)

我们可以将一个位置看作一个点坐标为\((pre_i,nxt_i)\)

要求横坐标\(<l\)且纵坐标\(>r\)

这个可以用简单\(kdTree\)

也可以用一个可持久化树套树强行维护一下

因为我写的时候还不会\(KDT\),所以用可持久化树套树强行维护了一波

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring> 
#include <cmath> 
#include <algorithm>
#include <set> 
using namespace std; 
inline int gi() {
    register int data = 0, w = 1;
    register char ch = 0;
    while (!isdigit(ch) && ch != '-') ch = getchar(); 
    if (ch == '-') w = -1, ch = getchar();
    while (isdigit(ch)) data = 10 * data + ch - '0', ch = getchar();
    return w * data; 
}
const int MAX_N = 100005;
int N, M;
struct Number { int val, pre, nxt, id; } a[MAX_N];
bool operator < (const Number &l, const Number r) { return l.pre < r.pre; } 
struct Prestree { int ls, rs, rt; } t[MAX_N * 22]; 
struct SGT { int ls, rs, mx; } It[MAX_N * 18 * 18]; 
int rt[MAX_N], tot, cnt; 
void ins(int &o, int p, int l, int r, int pos, int v) {
    o = ++tot; It[o] = It[p], It[o].mx = max(It[o].mx, v); 
    if (l == r) return ; 
    int mid = (l + r) >> 1; 
    if (pos <= mid) ins(It[o].ls, It[p].ls, l, mid, pos, v); 
    else ins(It[o].rs, It[p].rs, mid + 1, r, pos, v); 
}
void insert(int &o, int p, int l, int r, Number v) { 
    o = ++cnt; t[o] = t[p]; ins(t[o].rt, t[p].rt, 1, N, v.id, v.val);
    if (l == r) return ;
    int mid = (l + r) >> 1;
    if (v.nxt <= mid) insert(t[o].ls, t[p].ls, l, mid, v); 
    else insert(t[o].rs, t[p].rs, mid + 1, r, v); 
}
int que(int o, int l, int r, int ql, int qr) { 
    if (!o) return 0; 
    if (ql <= l && r <= qr) return It[o].mx; 
    int mid = (l + r) >> 1;
    if (qr <= mid) return que(It[o].ls, l, mid, ql, qr); 
    else if (ql > mid) return que(It[o].rs, mid + 1, r, ql, qr);
    else return max(que(It[o].ls, l, mid, ql, qr), que(It[o].rs, mid + 1, r, ql, qr)); 
} 
int query(int o, int l, int r, int pl, int pr, int ql, int qr) { 
    if (!o) return 0; 
    if (pl <= l && r <= pr) return que(t[o].rt, 1, N, ql, qr); 
    int mid = (l + r) >> 1;  
    if (pr <= mid) return query(t[o].ls, l, mid, pl, pr, ql, qr);
    else if (pl > mid) return query(t[o].rs, mid + 1, r, pl, pr, ql, qr);
    else return max(query(t[o].ls, l, mid, pl, pr, ql, qr), query(t[o].rs, mid + 1, r, pl, pr, ql, qr)); 
} 
set<int> s[MAX_N];
int ans = 0; 
int main () {
    N = gi(), M = gi();
    for (int i = 1; i <= N; i++) s[i].insert(1), s[i].insert(N + 2); 
    for (int i = 1; i <= N; i++) a[i].val = gi(), s[a[i].val].insert(i + 1), a[i].id = i; 
    for (int i = 1; i <= N; i++) { 
        set<int> :: iterator ite = s[a[i].val].find(i + 1); 
        a[i].pre = *--ite, ++ite, a[i].nxt = *++ite;
    }
    sort(&a[1], &a[N + 1]); 
    for (int i = 1, j = 1; i <= N + 2; i++) {
        rt[i] = rt[i - 1];
        while (j <= N && a[j].pre == i) insert(rt[i], rt[i], 1, N + 2, a[j++]); 
    } 
    while (M--) {
        int l = gi(), r = gi();
        l = (l + ans) % N + 1;
        r = (r + ans) % N + 1;
        if (r < l) swap(l, r);
        l++; r++;
        printf("%d\n", ans = query(rt[l - 1], 1, N + 2, r + 1, N + 2, l - 1, r - 1)); 
    } 
    return 0; 
} 
posted @ 2018-12-27 16:59  heyujun  阅读(295)  评论(3编辑  收藏  举报