[BZOJ 2653]middle
Description
一个长度为 $n$ 的序列 $A$ ,设其排过序之后为 $B$ ,其中位数定义为 $B\left[\left\lfloor\frac{n}{2}\right\rfloor\right]$ ,其中 $A,B$ 从 $0$ 开始标号。给你一个长度为 $n$ 的序列 $S$ 。回答 $Q$ 个这样的询问: $S$ 的左端点在 $[a,b]$ 之间,右端点在 $[c,d]$ 之间的子序列中,最大的中位数。
强制在线。
$1\leq n\leq 20000,1\leq Q\leq 25000$
Solution
二分答案。
对于 $<mid$ 的数变为 $-1$ ,而 $\geq mid$ 的数变为 $1$ 。
那么只要统计 $[a,b]$ 中的最大后缀, $(b,c)$ 总和,及 $[c,d]$ 中的最大前缀。
主席树维护,乱搞一下就好了。
Code
#include <bits/stdc++.h>
#define pb push_back
using namespace std;
const int N = 20000;
int n, Q, mp[N+5], a[N+5], tot, q[5], last_ans;
vector<int>to[N+5];
struct node {
int lmax, rmax, tol;
node (int _lmax = 0, int _rmax = 0, int _tol = 0) {lmax = _lmax, rmax = _rmax, tol = _tol; }
node operator + (const node &b) const {
node ans;
ans.tol = tol+b.tol, ans.lmax = max(lmax, tol+b.lmax), ans.rmax = max(b.rmax, b.tol+rmax);
return ans;
}
};
struct Segment_tree {
node sgm[N*50+5]; int ch[N*50+5][2], root[N+5], pos;
int cpynode(int o) {++pos; sgm[pos] = sgm[o]; ch[pos][0] = ch[o][0], ch[pos][1] = ch[o][1]; return pos; }
void build(int &o, int l, int r) {
o = cpynode(o); int mid = (l+r)>>1;
if (l == r) {sgm[o] = node(1, 1, 1); return; }
build(ch[o][0], l, mid); build(ch[o][1], mid+1, r);
sgm[o] = sgm[ch[o][0]]+sgm[ch[o][1]];
}
void update(int &o, int l, int r, int loc) {
o = cpynode(o); int mid = (l+r)>>1;
if (l == r) {sgm[o] = node(-1, -1, -1); return; }
if (loc <= mid) update(ch[o][0], l, mid, loc);
else update(ch[o][1], mid+1, r, loc);
sgm[o] = sgm[ch[o][0]]+sgm[ch[o][1]];
}
node query(int o, int l, int r, int a, int b) {
if (a <= l && r <= b) return sgm[o]; int mid = (l+r)>>1;
if (a <= mid && b > mid) return query(ch[o][0], l, mid, a, b)+query(ch[o][1], mid+1, r, a, b);
if (b <= mid) return query(ch[o][0], l, mid, a, b);
return query(ch[o][1], mid+1, r, a, b);
}
}T;
bool check(int x, int a, int b, int c, int d) {
int val = 0;
if (b+1 <= c-1) val = T.query(T.root[x], 1, n, b+1, c-1).tol;
val += T.query(T.root[x], 1, n, a, b).rmax+T.query(T.root[x], 1, n, c, d).lmax;
return val >= 0;
}
void work() {
scanf("%d", &n); tot = n;
for (int i = 1; i <= n; i++) scanf("%d", &a[i]), mp[i] = a[i];
sort(mp+1, mp+n+1); tot = unique(mp+1, mp+tot+1)-mp-1;
for (int i = 1; i <= n; i++) a[i] = lower_bound(mp+1, mp+tot+1, a[i])-mp, to[a[i]].pb(i);
T.build(T.root[1], 1, n);
for (int i = 2; i <= tot; i++) {
T.root[i] = T.root[i-1];
for (int j = 0, sz = to[i-1].size(); j < sz; j++)
T.update(T.root[i], 1, n, to[i-1][j]);
}
scanf("%d", &Q);
while (Q--) {
for (int i = 0; i < 4; i++) scanf("%d", &q[i]), (q[i] += last_ans) %= n, ++q[i];
sort(q, q+4);
int L = 1, R = tot;
while (L <= R) {
int mid = (L+R)>>1;
if (check(mid, q[0], q[1], q[2], q[3])) last_ans = mp[mid], L = mid+1;
else R = mid-1;
}
printf("%d\n", last_ans);
}
}
int main() {work(); return 0; }
博主蒟蒻,随意转载。但必须附上原文链接:http://www.cnblogs.com/NaVi-Awson/,否则你会终生找不到妹子!!!