import math # https://qiita.com/tomato1997/items/27581f530cdf77c79ad2 class Node: def __init__(self, default): self.rch = None self.lch = None self.val = default class PersistentSegTree: def __init__(self, ls, func, default, default_ver=0): ''' ls (list) : 永続配列にしたい配列 func: 関数を指定 default: 単位元を指定 default_ver (any): 最初のversion(デフォルト:0) ''' N = len(ls) self.default = default self.func = func self.N = N self.K = (N - 1).bit_length() self.N2 = 1 << self.K self.dat = [Node(self.default) for _ in range(2**(self.K + 1))] for i in range(self.N): # 葉の構築 self.dat[self.N2 + i].val = ls[i] self.build() self.verdict = dict() self.verdict[default_ver] = 1 # 各versionの根のindexを格納 def build(self): for node in range(self.N2 - 1, 0, -1): self.dat[node].rch = self.dat[node << 1 | 1] self.dat[node].lch = self.dat[node << 1] self.dat[node].val = self.func(self.dat[node << 1 | 1].val, self.dat[node << 1].val) self.dat.pop() self.dat.pop() def update_told_tnew_x_val(self, told, tnew, x, val): ''' version:toldのindex:xをvalに変更したものをtnewとする(O(logN)) told: 変更前のversion tnew: 変更後のversion x: 変更するindex val: 変更後の値 ''' if not (told in self.verdict): raise ('No such version exists') x += self.N2 path = bin(x)[3:] self.verdict[tnew] = len(self.dat) new_nodes = [Node(self.default) for _ in range(len(path) + 1)] v_old = self.dat[self.verdict[told]] v_new = new_nodes[0] now = 1 for i in path: # ノードをつなげる if i == '0': v_new.rch = v_old.rch v_new.lch = new_nodes[now] v_new = new_nodes[now] v_old = v_old.lch else: v_new.lch = v_old.lch v_new.rch = new_nodes[now] v_new = new_nodes[now] v_old = v_old.rch now += 1 v_new.val = val for node in range(len(path) - 1, -1, -1): # 付け加えたノードの値を子から親に更新 new_nodes[node].val = self.func(new_nodes[node].lch.val, new_nodes[node].rch.val) self.dat.append(new_nodes[0]) def query_t(self, t, L, R): ''' version:tにおける区間クエリ[L,R)(O(logN)) return : int ''' L += self.N2 R += self.N2 L0 = L R0 = R ls = set() # 見るべきノード番号 while L < R: if L & 1: ls.add(L) L += 1 if R & 1: R -= 1 ls.add(R) L >>= 1 R >>= 1 valdef = self.default d = [(1, 0, self.dat[self.verdict[t]])] while d: # 二分木上をdfs num, depth, node = d.pop() if num in ls: valdef = self.func(node.val, valdef) continue if depth == self.K: continue if num >= (L0 >> (self.K - depth)): d.append((num << 1, depth + 1, node.lch)) if R0 > ((num << 1 | 1) << (self.K - depth - 1)): d.append((num << 1 | 1, depth + 1, node.rch)) return valdef # (lmax, rmax, max, sum) def op(s, t): return (max(s[0], s[3] + t[0]), max(t[1], s[1] + t[3]), max(s[2], t[2], s[1] + t[0]), s[3] + t[3]) def main(): n, q = map(int, input().split()) a = list(map(int, input().split())) for i in range(n): a[i] -= 1 p = [(a[i], i) for i in range(n)] p.sort() init = [(1, 1, 1, 1) for _ in range(n)] seg = PersistentSegTree(init, op, (0, 0, 0, 0)) for i in range(n): seg.update_told_tnew_x_val(i, i + 1, p[i][1], (-1, -1, -1, -1)) for _ in range(q): l, r = map(int, input().split()) l -= 1 lo = -1 hi = n + 1 while hi - lo > 1: mi = (lo + hi) >> 1 s = seg.query_t(mi, l, r) if s[3] < 0 or s[3] - s[2] + 1 < 0: hi = mi else: lo = mi print(p[hi - 1][0] + 1) main()