• 【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
    ", ans = query(rt[l - 1], 1, N + 2, r + 1, N + 2, l - 1, r - 1)); 
        } 
        return 0; 
    } 
    
  • 相关阅读:
    Object转bigdecimal
    如何在A用户下建立视图,这个视图是A的表与B的表进行关联的?
    java.util.Date和java.sql.Date的区别和相互转化(转)
    JAVA如何获取GUID
    详解Oracle DELETE和TRUNCATE 的区别(摘)
    分开显示Excel2010打开的文档
    CentOS实验三:使用安装光盘建立本地软件源
    基本C库函数
    Shell_2(验证符合的输入)
    Shell_1(目录之间切换执行脚本)
  • 原文地址:https://www.cnblogs.com/heyujun/p/10185996.html
Copyright © 2020-2023  润新知