import std; void main () { int N, Q; readln.read(N, Q); auto A = readln.split.to!(int[]); solve(N, Q, A); } void solve (int N, int Q, int[] A) { // 座圧 + RSQ int[int] f; // ゴールからの距離 -> 全体の順番 int[] f_inv; { auto B = A.dup.sort.uniq.array; foreach (i; 0..B.length) f[B[i]] = i.to!int; f_inv.length = f.length; foreach (key, val; f) f_inv[val] = key; } auto RSQ = new SegmentTree!(int, (int a, int b) => a + b, () => 0)(N); foreach (a; A) RSQ.set(f[a], RSQ.get(f[a]) + 1); foreach (i; 0..Q) { int x, y; readln.read(x, y); x--, y--; // A[y] < hoge < A[x] if (f[A[x]] <= f[A[y]]) { writeln(0); continue; } writeln(RSQ.prod(f[A[y]] + 1, f[A[x]])); } } void read (T...) (string S, ref T args) { import std.conv : to; import std.array : split; auto buf = S.split; foreach (i, ref arg; args) { arg = buf[i].to!(typeof(arg)); } } import std.traits : ReturnType, isCallable, Parameters; import std.meta : AliasSeq; class SegmentTree (T, alias ope, alias e) if ( isCallable!(ope) && isCallable!(e) && is (ReturnType!(ope) == T) && is (ReturnType!(e) == T) && is (Parameters!(ope) == AliasSeq!(T, T)) && is (Parameters!(e) == AliasSeq!()) ) { /* 内部の配列が1-indexedで2冪のセグメントツリー */ import std.format : format; T[] X; size_t length; /* --- Constructors --- */ this (size_t length_) { adjust_array_length(length_); for (size_t i = length; i < 2*length; i++) { X[i] = e(); } build(); } import std.range.primitives : isInputRange; this (R) (R Range) if (isInputRange!(R) && is (ElementType!(R) == T)) { adjust_array_length(walkLength(Range)); size_t i = length; foreach (item; Range) { X[i] = item; i++; } while (i < 2*length) { X[i] = e(); i++; } build(); } /* --- Functions --- */ private void adjust_array_length (size_t length_) { length = 1; while (length <= length_) length *= 2; X = new T[](2*length); } void set_with_no_update (size_t idx, T val) in { assert(idx < length, format("In function \"set_with_no_update\", idx is out of range. (length = %s idx = %s)", length, idx)); } do { X[length+idx] = val; } void build () { for (size_t i = length-1; 1 <= i; i--) { X[i] = ope(X[2*i], X[2*i+1]); } } public override string toString () { string res = ""; int level = 1; while ((2^^(level-1)) < X.length) { res ~= format("level: %2s | ", level); for (size_t i = (2^^(level-1)); i < (2^^level); i++) { res ~= format("%s%s", X[i], (i == (2^^level)-1 ? "\n" : " ")); } level++; } return res; } void set (size_t idx, T val) in { assert(idx < length, format("In function \"set\", idx is out of range. (length = %s idx = %s)", length, idx)); } do { idx += length; X[idx] = val; while (2 <= idx) { idx /= 2; X[idx] = ope(X[2*idx], X[2*idx+1]); } } T get (size_t idx) in { assert(idx < length, format("In function \"get\", idx is out of range. (length = %s idx = %s)", length, idx)); } do { idx += length; return X[idx]; } T prod (size_t l, size_t r) in { assert(l < length, format("In function \"prod\", l is out of range. (length = %s l = %s)", length, l)); assert(r <= length, format("In function \"prod\", r is out of range. (length = %s r = %s)", length, r)); assert(l <= r, format("In function \"prod\", l < r must be satisfied. (length = %s l = %s, r = %s)", length, l, r)); } do { /* Returns all prod O(1) */ if (l == 0 && r == length) return X[1]; if (l == r) return e(); /* Closed interval [l, r] */ r--; l += length, r += length; T LeftProd, RightProd; LeftProd = RightProd = e(); while (l <= r) { if (l % 2 == 1) { LeftProd = ope(LeftProd, X[l]); l++; } if (r % 2 == 0) { RightProd = ope(X[r], RightProd); r--; } l /= 2; r /= 2; } return ope(LeftProd, RightProd); } }