1. 程式人生 > >【BZOJ】A simple rmq problem

【BZOJ】A simple rmq problem

【BZOJ】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; 
}