ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

BZOJ 3489: A simple rmq problem

2020-03-05 23:01:05  阅读:224  来源: 互联网

标签:3489 ccnt return simple tree int problem MOD define


对每一个位置 \(i\),求出其上一次出现的位置 \(pre_i\) 以及下一次出现的位置 \(next_i\)
对一个询问来说,就是查询 \(pre_i\) 在 \([0,l-1]\),\(i\) 在 \([l, r]\),\(next_i\) 在 \([r + 1, n + 1]\) 这个长方体内的最大值
那么可以用KD-tree维护
空间复杂度为 \(O(n)\),时间不知,但是跑得挺快的
也可以树套树做
考虑一个位置能对哪些区间做出贡献
即左端点在区间 \([pre_i + 1, i]\),右端点在 \([i, next_i - 1]\) 的区间
把左端点看成横坐标右端点看成纵坐标
就变成了对一个区间的贡献
查询就变成了查询一个点的值
使用线段树套线段树维护
复杂度 \(O(n \log^2 n)\)

/***** KD-tree *****/
#include <bits/stdc++.h>
#define pb push_back
#define fi first
#define se second
#define pii pair<int, int>
#define pli pair<ll, int>
#define lp tree[p].l
#define rp tree[p].r
#define mid ((l + r) / 2)
#define lowbit(i) ((i) & (-i))
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
#define rep(i,a,b) for(int i=a;i<b;i++)
#define per(i,a,b) for(int i=b-1;i>=a;i--)
#define Edg int ccnt=1,head[N],to[E],ne[E];void addd(int u,int v){to[++ccnt]=v;ne[ccnt]=head[u];head[u]=ccnt;}void add(int u,int v){addd(u,v);addd(v,u);}
#define Edgc int ccnt=1,head[N],to[E],ne[E],c[E];void addd(int u,int v,int w){to[++ccnt]=v;ne[ccnt]=head[u];c[ccnt]=w;head[u]=ccnt;}void add(int u,int v,int w){addd(u,v,w);addd(v,u,w);}
#define es(u,i,v) for(int i=head[u],v=to[i];i;i=ne[i],v=to[i])
const int MOD = 1e9 + 7;
void M(int &x) {if (x >= MOD)x -= MOD; if (x < 0)x += MOD;}
int qp(int a, int b = MOD - 2) {int ans = 1; for (; b; a = 1LL * a * a % MOD, b >>= 1)if (b & 1)ans = 1LL * ans * a % MOD; return ans % MOD;}
template<class T>T gcd(T a, T b) { while (b) { a %= b; std::swap(a, b); } return a; }
template<class T>bool chkmin(T &a, T b) { return a > b ? a = b, 1 : 0; }
template<class T>bool chkmax(T &a, T b) { return a < b ? a = b, 1 : 0; }
char buf[1 << 21], *p1 = buf, *p2 = buf;
inline char getc() {
    return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++;
}
inline int _() {
    int x = 0, f = 1; char ch = getc();
    while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getc(); }
    while (ch >= '0' && ch <= '9') { x = x * 10ll + ch - 48; ch = getc(); }
    return x * f;
}

const int N = 1e5 + 7;
int D, n, m, root, a[N], pos[N], pre[N], suf[N], ans;
int L[3], R[3];
struct P {
    int l, r;
    int d[3], mn[3], mx[3], val, mxv;
    P() {}
    P(int a, int b, int c, int v): val(v) {
        d[0] = a, d[1] = b, d[2] = c;
        mxv = val;
        rep (i, 0, 3) mn[i] = mx[i] = d[i];
    }
    bool operator < (const P &p) const { return d[D] < p.d[D]; }
} tree[N];

inline void tag(int p, int x) {
    chkmax(tree[p].mxv, tree[x].mxv);
    rep (i, 0, 3) chkmin(tree[p].mn[i], tree[x].mn[i]), chkmax(tree[p].mx[i], tree[x].mx[i]);
}
void pushup(int p) {
    if (lp) tag(p, lp);
    if (rp) tag(p, rp);
}
int build(int l, int r, int d) {
    if (l > r) return 0;
    D = d;
    std::nth_element(tree + l, tree + mid + 1, tree + r + 1);
    int p = mid;
    lp = build(l, mid - 1, (d + 1) % 3);
    rp = build(mid + 1, r, (d + 1) % 3);
    pushup(p);
    return p;
}
bool checkALL(int p) {
    rep (i, 0, 3) if (tree[p].mn[i] < L[i] || tree[p].mx[i] > R[i]) return 0;
    return 1;
}
bool check(int p) {
    rep (i, 0, 3) if (tree[p].d[i] < L[i] || tree[p].d[i] > R[i]) return 0;
    return 1;
}
bool pbin(int p) { 
    rep (i, 0, 3) if (tree[p].mx[i] < L[i] || tree[p].mn[i] > R[i]) return 0;
    return 1;
}
void query(int p) {
    if (!p) return;
    if (tree[p].mxv <= ans) return;
    if (checkALL(p)) { chkmax(ans, tree[p].mxv); return; }
    if (check(p)) chkmax(ans, tree[p].val);
    int dl = 0, dr = 0;
    if (lp) dl = pbin(lp);
    if (rp) dr = pbin(rp);
    if (dl > dr) {
        if (dl) query(lp);
        if (dr) query(rp);
    } else {
        if (dr) query(rp);
        if (dl) query(lp);
    }
}

int main() {
#ifdef LOCAL
    freopen("ans.out", "w", stdout);
#endif
    n = _(), m = _();
    rep (i, 1, n + 1) {
        a[i] = _();
        pre[i] = pos[a[i]];
        pos[a[i]] = i;
    }
    rep (i, 1, n + 1) pos[i] = n + 1;
    per (i, 1, n + 1) {
        suf[i] = pos[a[i]];
        pos[a[i]] = i;
    }
    rep (i, 1, n + 1) tree[i] = P(i, pre[i], suf[i], a[i]);
    root = build(1, n, 0);
    rep (i, 0, m) {
        int l = _(), r = _();
        l = (l + ans) % n + 1, r = (r + ans) % n + 1;
        if (l > r) std::swap(l, r);
        ans = 0;
        L[0] = l, R[0] = r;
        L[1] = 0, R[1] = l - 1;
        L[2] = r + 1, R[2] = n + 1;
        query(root);
        printf("%d\n", ans);
    }
#ifdef LOCAL
    printf("%.10f\n", (db)clock() / CLOCKS_PER_SEC);
#endif
    return 0;
}
#include <bits/stdc++.h>
#define pb push_back
#define fi first
#define se second
#define pii pair<int, int>
#define pli pair<ll, int>
#define lp p << 1
#define rp p << 1 | 1
#define mid ((l + r) / 2)
#define lowbit(i) ((i) & (-i))
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
#define rep(i,a,b) for(int i=a;i<b;i++)
#define per(i,a,b) for(int i=b-1;i>=a;i--)
#define Edg int ccnt=1,head[N],to[E],ne[E];void addd(int u,int v){to[++ccnt]=v;ne[ccnt]=head[u];head[u]=ccnt;}void add(int u,int v){addd(u,v);addd(v,u);}
#define Edgc int ccnt=1,head[N],to[E],ne[E],c[E];void addd(int u,int v,int w){to[++ccnt]=v;ne[ccnt]=head[u];c[ccnt]=w;head[u]=ccnt;}void add(int u,int v,int w){addd(u,v,w);addd(v,u,w);}
#define es(u,i,v) for(int i=head[u],v=to[i];i;i=ne[i],v=to[i])
const int MOD = 1e9 + 7;
void M(int &x) {if (x >= MOD)x -= MOD; if (x < 0)x += MOD;}
int qp(int a, int b = MOD - 2) {int ans = 1; for (; b; a = 1LL * a * a % MOD, b >>= 1)if (b & 1)ans = 1LL * ans * a % MOD; return ans % MOD;}
template<class T>T gcd(T a, T b) { while (b) { a %= b; std::swap(a, b); } return a; }
template<class T>bool chkmin(T &a, T b) { return a > b ? a = b, 1 : 0; }
template<class T>bool chkmax(T &a, T b) { return a < b ? a = b, 1 : 0; }
char buf[1 << 21], *p1 = buf, *p2 = buf;
inline char getc() {
    return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++;
}
inline int _() {
    int x = 0, f = 1; char ch = getc();
    while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getc(); }
    while (ch >= '0' && ch <= '9') { x = x * 10ll + ch - 48; ch = getc(); }
    return x * f;
}

const int N = 1e5 + 7;
int n, m, a[N], pos[N], pre[N], suf[N], ans;

struct Inseg {
    static const int Nn = N * 200;
    int mx[Nn], tag[Nn];
    int ch[Nn][2], tol;
    void update(int &p, int l, int r, int x, int y, int v) {
        if (!p) p = ++tol;
        chkmax(mx[p], v);
        if (x <= l && y >= r) {
            chkmax(tag[p], v);
            return;
        }
        if (x <= mid) update(ch[p][0], l, mid, x, y, v);
        if (y > mid) update(ch[p][1], mid + 1, r, x, y, v);
    }
    void query(int p, int l, int r, int x) {
        if (!p || mx[p] <= ans) return;
        chkmax(ans, tag[p]);
        if (l == r) return;
        if (x <= mid) query(ch[p][0], l, mid, x);
        else query(ch[p][1], mid + 1, r, x);
    }
} in;
struct Outseg {
    int mx[N << 2], tag[N << 2];
    void update(int p, int l, int r, int x, int y, int z, int v) {
        chkmax(mx[p], v);
        if (x <= l && y >= r) {
            in.update(tag[p], 0, n + 1, y, z, v);
            return;
        }
        if (x <= mid) update(lp, l, mid, x, y, z, v);
        if (y > mid) update(rp, mid + 1, r, x, y, z, v);
    }
    void query(int p, int l, int r, int x, int y) {
        if (mx[p] <= ans) return;
        in.query(tag[p], 0, n + 1, y);
        if (l == r) return;
        if (x <= mid) query(lp, l, mid, x, y);
        else query(rp, mid + 1, r, x, y);
    }
} out;

int main() {
#ifdef LOCAL
    freopen("ans.out", "w", stdout);
#endif
    //printf("%f\n", (db)(sizeof(in) + sizeof(out)) / 1024 / 1024);
    n = _(), m = _();
    rep (i, 1, n + 1) {
        a[i] = _();
        pre[i] = pos[a[i]];
        pos[a[i]] = i;
    }
    rep (i, 1, n + 1) pos[i] = n + 1;
    per (i, 1, n + 1) {
        suf[i] = pos[a[i]];
        pos[a[i]] = i;
    }
    rep (i, 1, n + 1) out.update(1, 1, n, pre[i] + 1, i, suf[i] - 1, a[i]);
    rep (i, 0, m) {
        int l = _(), r = _();
        l = (l + ans) % n + 1, r = (r + ans) % n + 1;
        if (l > r) std::swap(l, r);
        ans = 0;
        out.query(1, 1, n, l, r);
        printf("%d\n", ans);
    }
#ifdef LOCAL
    printf("%.10f\n", (db)clock() / CLOCKS_PER_SEC);
#endif
    return 0;
}

标签:3489,ccnt,return,simple,tree,int,problem,MOD,define
来源: https://www.cnblogs.com/Mrzdtz220/p/12423524.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有