#include using namespace std; // 64-ary predecessor structure for universe [0, 2^(6*LEVEL)) struct Pred64 { static constexpr int LEVEL = 4; // 64^4 = 2^24 static constexpr int UNIV = 1 << (6 * LEVEL); // 2^24 = 16,777,216 array, LEVEL> d; Pred64() { for (int i = 0; i < LEVEL; ++i) { int sz = 1 << (6 * (LEVEL - i - 1)); d[i].assign(sz, 0); } } inline bool empty() const { return d[LEVEL - 1][0] == 0; } inline void add(int x) { unsigned ux = (unsigned)x; for (int i = 0; i < LEVEL; ++i) { unsigned idx = ux >> (6 * (i + 1)); unsigned bit = (ux >> (6 * i)) & 63U; uint64_t &w = d[i][idx]; uint64_t before = w; w |= 1ULL << bit; if (w == before) break; } } inline void remove(int x) { unsigned ux = (unsigned)x; for (int i = 0; i < LEVEL; ++i) { unsigned idx = ux >> (6 * (i + 1)); unsigned bit = (ux >> (6 * i)) & 63U; uint64_t &w = d[i][idx]; w &= ~(1ULL << bit); if (w != 0) break; } } // max element <= x, or -1 if none inline int prev(int x) const { if (empty()) return -1; if (x < 0) return -1; if (x >= UNIV) x = UNIV - 1; unsigned ux = (unsigned)x; // l=0: can take <= pos inside the same 64-bit word. { unsigned idx = ux >> 6; unsigned pos = ux & 63U; uint64_t mask = (pos == 63) ? ~0ULL : ((1ULL << (pos + 1)) - 1ULL); uint64_t w = d[0][idx] & mask; if (w) return (int)((idx << 6) | (unsigned)(63 - __builtin_clzll(w))); } // higher levels: must choose strictly smaller child than pos for (int l = 1; l < LEVEL; ++l) { unsigned idx = ux >> (6 * (l + 1)); unsigned pos = (ux >> (6 * l)) & 63U; uint64_t mask = (pos == 0) ? 0ULL : ((1ULL << pos) - 1ULL); // bits < pos uint64_t w = d[l][idx] & mask; if (!w) continue; int child = 63 - __builtin_clzll(w); int res = (int)idx; res = (res << 6) | child; for (int t = l - 1; t >= 0; --t) { uint64_t w2 = d[t][(unsigned)res]; int c = 63 - __builtin_clzll(w2); res = (res << 6) | c; } return res; } return -1; } // min element >= x, or UNIV if none inline int next(int x) const { if (empty()) return UNIV; if (x < 0) x = 0; if (x >= UNIV) return UNIV; unsigned ux = (unsigned)x; // l=0: can take >= pos inside the same 64-bit word. { unsigned idx = ux >> 6; unsigned pos = ux & 63U; uint64_t mask = (~0ULL) << pos; uint64_t w = d[0][idx] & mask; if (w) return (int)((idx << 6) | (unsigned)__builtin_ctzll(w)); } // higher levels: must choose strictly larger child than pos for (int l = 1; l < LEVEL; ++l) { unsigned idx = ux >> (6 * (l + 1)); unsigned pos = (ux >> (6 * l)) & 63U; if (pos == 63) continue; uint64_t mask = (~0ULL) << (pos + 1); // bits > pos uint64_t w = d[l][idx] & mask; if (!w) continue; int child = __builtin_ctzll(w); int res = (int)idx; res = (res << 6) | child; for (int t = l - 1; t >= 0; --t) { uint64_t w2 = d[t][(unsigned)res]; int c = __builtin_ctzll(w2); res = (res << 6) | c; } return res; } return UNIV; } }; static inline uint64_t hilbertOrder(int x, int y, int pow = 17, int rot = 0) { if (pow == 0) return 0; int h = 1 << (pow - 1); int seg; if (x < h) seg = (y < h) ? 0 : 1; else seg = (y < h) ? 3 : 2; seg = (seg + rot) & 3; static const int rotateDelta[4] = {3, 0, 0, 1}; int nx = x & (h - 1); int ny = y & (h - 1); int nrot = (rot + rotateDelta[seg]) & 3; uint64_t sub = hilbertOrder(nx, ny, pow - 1, nrot); uint64_t add = (uint64_t)seg << (2 * pow - 2); if (seg == 1 || seg == 2) return add + sub; return add + ((1ULL << (2 * pow - 2)) - 1ULL - sub); } struct Query { int l, r, x; char c; int idx; uint64_t ord; }; static const int MAXV = 10000000; static vector valCnt, gapCnt; static Pred64 valSet, gapSet; static vector A; static inline void add_gap(int g) { int &cnt = gapCnt[g]; if (cnt == 0) gapSet.add(g); ++cnt; } static inline void remove_gap(int g) { int &cnt = gapCnt[g]; --cnt; if (cnt == 0) gapSet.remove(g); } static inline void add_index(int idx) { int v = A[idx]; int &cv = valCnt[v]; if (cv == 0) { int p = valSet.prev(v); // < v (since v not present) int n = valSet.next(v); // > v (since v not present) if (p != -1 && n != Pred64::UNIV) remove_gap(n - p); if (p != -1) add_gap(v - p); if (n != Pred64::UNIV) add_gap(n - v); valSet.add(v); cv = 1; } else { add_gap(0); ++cv; } } static inline void remove_index(int idx) { int v = A[idx]; int &cv = valCnt[v]; if (cv == 1) { int p = valSet.prev(v - 1); // < v int n = valSet.next(v + 1); // > v if (p != -1) remove_gap(v - p); if (n != Pred64::UNIV) remove_gap(n - v); if (p != -1 && n != Pred64::UNIV) add_gap(n - p); valSet.remove(v); cv = 0; } else { remove_gap(0); --cv; } } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int N, Q; cin >> N >> Q; A.assign(N + 1, 0); for (int i = 1; i <= N; ++i) cin >> A[i]; valCnt.assign(MAXV + 1, 0); gapCnt.assign(MAXV + 1, 0); vector queries; queries.reserve(Q); for (int i = 0; i < Q; ++i) { Query qu; cin >> qu.l >> qu.r >> qu.x >> qu.c; qu.idx = i; qu.ord = hilbertOrder(qu.l - 1, qu.r - 1); queries.push_back(qu); } sort(queries.begin(), queries.end(), [](const Query &a, const Query &b) { return a.ord < b.ord; }); vector ans(Q, -1); int curL = 1, curR = 0; for (const auto &qu : queries) { while (curL > qu.l) add_index(--curL); while (curR < qu.r) add_index(++curR); while (curL < qu.l) remove_index(curL++); while (curR > qu.r) remove_index(curR--); if (gapSet.empty()) { ans[qu.idx] = -1; continue; } if (qu.c == 'L') { int v = gapSet.prev(qu.x); ans[qu.idx] = (v == -1) ? -1 : v; } else { int v = gapSet.next(qu.x); ans[qu.idx] = (v == Pred64::UNIV) ? -1 : v; } } for (int i = 0; i < Q; ++i) cout << ans[i] << '\n'; return 0; }