#pragma GCC optimize ("O3") #pragma GCC target ("sse4") #include #define rep(i,n) for (int i = 0; i < (n); ++i) #define rrep(i,n) for (int i = (n)-1; i >= 0; --i) #define chmax(a, b) a = max(a, b) #define chmin(a, b) a = min(a, b) #define all(x) (x).begin(), (x).end() #define rall(x) (x).rbegin(), (x).rend() using namespace std; using ll = long long; using P = pair; using VI = vector; using VVI = vector; template struct persistent_segtree { struct Node { Node *lch, *rch; S d; }; Node node_pool[1 + (height + 1) * update_query_num]; int last_node = 0; Node *nil = &node_pool[0]; Node *root[1 + update_query_num]; int last_root = 0; const int n; persistent_segtree(int n): n(n) { assert(n <= (1 << height)); nil->lch = nil->rch = nil; nil->d = e(); root[0] = nil; } int set(int p, S x, int rev=-1) { Node *now = (rev == -1 ? root[last_root] : root[rev]); Node *path[height + 1]; path[0] = now; bool took_left[height]; int idx = 0; int l = 0, r = n; while(r - l != 1) { int m = (l + r) / 2; if (p < m) { now = now->lch; took_left[idx] = true; r = m; } else { now = now->rch; took_left[idx] = false; l = m; } path[++idx] = now; } Node *pre = &node_pool[++last_node]; pre->d = x; for(--idx; idx >= 0; --idx) { Node *nd = &node_pool[++last_node]; if (took_left[idx]) { nd->lch = pre; nd->rch = path[idx]->rch; } else { nd->lch = path[idx]->lch; nd->rch = pre; } nd->d = op(nd->lch->d, nd->rch->d); pre = nd; } root[++last_root] = pre; return last_root; } S get(int p, int rev=-1) { Node *now = (rev == -1 ? root[last_root] : root[rev]); int l = 0, r = n; while(r - l != 1) { int m = (r + l) / 2; if (p < m) { now = now->lch; r = m; } else { now = now->rch; l = m; } } return now->d; } S prod(int l, int r, int rev=-1) { Node *now = (rev == -1 ? root[last_root] : root[rev]); return prod_sub(l, r, 0, n, now); } S prod_sub(int l, int r, int lb, int rb, Node *x) { if (x == nil) return e(); if (r <= lb || rb <= l) return e(); if (l <= lb && rb <= r) return x->d; int m = (lb + rb) / 2; return op( prod_sub(l, r, lb, m, x->lch), prod_sub(l, r, m, rb, x->rch) ); } void reconstruct_array(int *ret, int rev=-1) { Node *rt = (rev == -1 ? root[last_root] : root[rev]); int ptr = -1; //std::vector ret; //ret.reserve(n); int l = 0, r = n; struct node_range { Node *x; int l, r; } nr[height]; nr[0] = {rt, 0, n}; for(int idx = 0; idx >= 0;) { Node *now = nr[idx].x; int l = nr[idx].l, r = nr[idx].r; --idx; if (r - l == 1) { ret[++ptr] = now->d; } else { int m = (r + l) / 2; nr[++idx] = {now->rch, m, r}; nr[++idx] = {now->lch, l, m}; } } return;// ret; } }; int op(int x, int y) {return x + y;} int e() {return 0;} const int MX = 20001; int arr_f[MX], arr_b[MX]; int main() { cin.tie(0); ios::sync_with_stdio(0); int n, q; scanf("%d%d", &n, &q); VI a(n); rep(i, n) scanf("%d", a.data() + i); persistent_segtree st_f(MX), st_b(MX); VI s_f(n+1), s_b(n+1); int now = 0; rep(i, n) { now += st_f.prod(a[i] + 1, MX); s_f[i+1] = now; st_f.set(a[i], st_f.get(a[i]) + 1); } now = 0; rrep(i, n) { now += st_b.prod(0, a[i]); s_b[i] = now; st_b.set(a[i], st_b.get(a[i]) + 1); } while(q--) { int l, r; scanf("%d%d", &l, &r); --l, --r; int ans = s_f[l] + s_b[r+1]; st_f.reconstruct_array(arr_f, l); st_b.reconstruct_array(arr_b, n-r-1); int t = 2e9; int aacc = 0, bacc = 0; for(int x = 1; x < MX; ++x) { ans += arr_f[x] * bacc; aacc += arr_f[x]; int nt = l - aacc + bacc; chmin(t, nt); bacc += arr_b[x]; } ans += t * (r - l + 1); printf("%d\n", ans); } }