回答 Q Q 个这样的询问:
序列 s s 的左端点在 [a,b] [ a , b ] 之间,右端点在 [c,d] [ c , d ] 之间的子序列中,最大的中位数。其中 a<b<c<d a < b < c < d ,位置也从0开始标号。
对于每个询问二分答案 k k ,比 k k 小的设为 −1 − 1 ,大于等于 k k 则设为 1 1 ,判断能否使区间和 ≥0 ≥ 0 .
考虑按照大小顺序构建二分时的 (1,−1) ( 1 , − 1 ) 序列,那么每次只会修改一个位置,主席树维护即可。
#include
using namespace std;
const int maxn = 20005;
int n, A[maxn], Id[maxn], Q;
inline int gi()
{
char c = getchar();
while (c < '0' || c > '9') c = getchar();
int sum = 0;
while ('0' <= c && c <= '9') sum = sum * 10 + c - 48, c = getchar();
return sum;
}
int root[maxn];
namespace pret
{
struct node {
int sum, suml, sumr;
int lch, rch;
void clear()
{
sum = 0; suml = -n - 1; sumr = -n - 1;
}
} t[maxn * 20], Ans;
int tot;
#define mid ((l + r) >> 1)
void merge(node &s, node a, node b)
{
s.sum = a.sum + b.sum;
s.suml = max(a.suml, b.suml + a.sum);
s.sumr = max(b.sumr, a.sumr + b.sum);
}
void build(int &s, int l, int r)
{
s = ++tot;
if (l == r) {
t[s].sum = t[s].suml = t[s].sumr = 1;
return ;
}
build(t[s].lch, l, mid);
build(t[s].rch, mid + 1, r);
merge(t[s], t[t[s].lch], t[t[s].rch]);
}
void modify(int &s, int l, int r, int v)
{
t[++tot] = t[s]; s = tot;
if (l == r) {
t[s].sum = t[s].suml = t[s].sumr = -1;
return ;
}
if (v <= mid) modify(t[s].lch, l, mid, v);
else modify(t[s].rch, mid + 1, r, v);
merge(t[s], t[t[s].lch], t[t[s].rch]);
}
void query(int s, int l, int r, int x, int y)
{
if (x <= l && r <= y) {
merge(Ans, Ans, t[s]); return ;
}
if (x <= mid) query(t[s].lch, l, mid, x, y);
if (y >= mid + 1) query(t[s].rch, mid + 1, r, x, y);
}
}
inline bool cmp(const int &x, const int &y)
{
return A[x] < A[y];
}
int a, b, c, d;
inline bool check(int x)
{
int sum = 0;
pret::Ans.clear();
if (b + 1 <= c - 1) pret::query(root[x], 1, n, b + 1, c - 1), sum += pret::Ans.sum;
pret::Ans.clear(); pret::query(root[x], 1, n, a, b); sum += pret::Ans.sumr;
pret::Ans.clear(); pret::query(root[x], 1, n, c, d); sum += pret::Ans.suml;
return sum >= 0;
}
int main()
{
freopen("middle.in", "r", stdin);
freopen("middle.out", "w", stdout);
n = gi();
for (int i = 1; i <= n; ++i) A[i] = gi(), Id[i] = i;
sort(Id + 1, Id + n + 1, cmp);
pret::build(root[1], 1, n);
for (int i = 2; i <= n; ++i)
root[i] = root[i - 1], pret::modify(root[i], 1, n, Id[i - 1]);
int lastans = 0;
Q = gi();
for (int i = 1; i <= Q; ++i) {
a = gi(); b = gi(); c = gi(); d = gi();
int q[4] = {(a + lastans) % n, (b + lastans) % n, (c + lastans) % n, (d + lastans) % n};
sort(q, q + 4);
a = q[0] + 1; b = q[1] + 1; c = q[2] + 1; d = q[3] + 1;
int l = 1, r = n, Mid;
while (l < r) {
Mid = (l + r + 1) >> 1;
if (check(Mid)) l = Mid;
else r = Mid - 1;
}
printf("%d\n", lastans = A[Id[l]]);
}
return 0;
}