Problem surface
solution
In fact, this problem is not strictly a presidential tree, but a persistent segment tree.
- Obviously the answer satisfies monotonicity. Assuming that our current dichotomy is mid mid mid, the corresponding median is a[mid]a[mid]a[mid](a[mid]a[mid]a[mid] a [mid] a [mid], which means that the mid mid mid mid mid is small after the order is completed from small to large, not the number in this sequence can obviously be ignored. Then change the number less than it to - 1 and the other numbers to 1. Then for [a,b],[c,d][a,b],[c,d][a,b],[c,d], [b, c], [b,c][b,c][b,c], [b, c], [b] the part must be selected, the other parts to be selected are the maximum suffix of [a,b_1][a,b-1][a,b_1] and the maximum prefix and suffix of [c+1,d][c+1,d][c+1,d]. If the maximum of the sum of the selected numbers is non-negative, midmidmid midmid is legal.
- Then we find that the time complexity of this method is O (nq log n) O (nq log n) O (nq log n), which may be worse, obviously not.
- Then we will consider how to optimize this approach.
- Consider building a segment tree for each number, the number smaller than it is - 1, not less than its number is 1, and then maintaining the maximum prefix sum, the maximum suffix sum and the interval sum for each segment.
- Then we only need to query the corresponding segment tree and the relevant information every time we divide it into two parts.
- Time complexity: O (q log 2n) O (q log ^ 2n) O (q log 2n), but space seems to explode...
- Then we find that the only difference between I I I and i_1i-1i_1 is that the position of the number corresponding to a[i_1]a[i-1]a[i_1] has changed from 1 to 1 in I I I. So since only this point has changed, we can use the persistent segment tree directly to maintain the process.
- Time complexity: O (q log 2n) O (q log ^ 2n) O (q log 2n), space complexity: O (n log n) O (n log n) O (n log n), enough to pass this problem.
Code
#include <bits/stdc++.h> #define PI pair <int, int> #define mp make_pair #define inf 1 << 30 #define N 20010 using namespace std; template <typename node> void read(node &x) { x = 0; int f = 1; char c = getchar(); while (!isdigit(c)) {if (c == '-') f = -1; c = getchar();} while (isdigit(c)) x = x * 10 + c - '0', c = getchar(); x *= f; } int max(int x, int y) {return x > y ? x : y;} struct Info { int val, id; bool operator < (const Info &a) const {return val < a.val;} } a[N]; struct SegmentTree { struct Node {int lc, rc, sum, mxl, mxr;} t[N * 35]; int tot; int mxl(int k) {return t[k].mxl;} int mxr(int k) {return t[k].mxr;} int sum(int k) {return t[k].sum;} void update(int k) { int lc = t[k].lc, rc = t[k].rc; t[k].sum = sum(lc) + sum(rc); t[k].mxl = max(sum(lc) + mxl(rc), mxl(lc)); t[k].mxr = max(sum(rc) + mxr(lc), mxr(rc)); } void build(int &k, int l, int r) { k = ++tot; if (l == r) return t[k] = (Node) {0, 0, 1, 1, 1}, void(); int mid = (l + r) >> 1; build(t[k].lc, l, mid), build(t[k].rc, mid + 1, r); update(k); } void ins(int &cur, int k, int l, int r, int x) { cur = ++tot; t[cur] = t[k]; if (l == r) return t[cur].sum = t[cur].mxl = t[cur].mxr = -1, void(); int mid = (l + r) >> 1; if (x <= mid) ins(t[cur].lc, t[k].lc, l, mid, x); else ins(t[cur].rc, t[k].rc, mid + 1, r, x); update(cur); } PI queryl(int k, int l, int r, int L, int R) { if (L > R) return mp(0, 0); if (L <= l && r <= R) return mp(t[k].sum, t[k].mxl); int mid = (l + r) >> 1; if (R <= mid) return queryl(t[k].lc, l, mid, L, R); if (L > mid) return queryl(t[k].rc, mid + 1, r, L, R); PI tx = queryl(t[k].lc, l, mid, L, mid), ty = queryl(t[k].rc, mid + 1, r, mid + 1, R), ret; ret.first = tx.first + ty.first, ret.second = max(tx.first + ty.second, tx.second); return ret; } PI queryr(int k, int l, int r, int L, int R) { if (L > R) return mp(0, 0); if (L <= l && r <= R) return mp(t[k].sum, t[k].mxr); int mid = (l + r) >> 1; if (R <= mid) return queryr(t[k].lc, l, mid, L, R); if (L > mid) return queryr(t[k].rc, mid + 1, r, L, R); PI tx = queryr(t[k].lc, l, mid, L, mid), ty = queryr(t[k].rc, mid + 1, r, mid + 1, R), ret; ret.first = tx.first + ty.first, ret.second = max(ty.first + tx.second, ty.second); return ret; } } T; int rt[N]; int main() { int n; read(n); for (int i = 1; i <= n; i++) read(a[i].val), a[i].id = i; sort(a + 1, a + n + 1); T.build(rt[1], 1, n); for (int i = 2; i <= n; i++) T.ins(rt[i], rt[i - 1], 1, n, a[i - 1].id); int q, las = 0; read(q); while (q--) { int tx[4]; for (int i = 0; i < 4; i++) read(tx[i]), tx[i] = (tx[i] + las) % n + 1; sort(tx, tx + 4); int l1 = tx[0], r1 = tx[1], l2 = tx[2], r2 = tx[3], l = 1, r = n, ans; while (l <= r) { int mid = (l + r) >> 1, sum = 0; PI tx = T.queryr(rt[mid], 1, n, l1, r1 - 1), ty = T.queryl(rt[mid], 1, n, r1, l2), tz = T.queryl(rt[mid], 1, n, l2 + 1, r2); sum = ty.first + max(0, tx.second) + max(0, tz.second); if (sum >= 0) ans = mid, l = mid + 1; else r = mid - 1; } las = a[ans].val; cout << a[ans].val << "\n"; } return 0; }