BZOJ 3489: A simple rmq problem
作者:互联网
对每一个位置 \(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