#define int long long constint N = 50010, M = 320; int n, m, k, now, a[N], cnt[N], ans[N];
voidread(int& t){ t = 0; char ch = getchar(); while (!isdigit(ch)) ch = getchar(); while (isdigit(ch)) t = t*10 + (ch^48), ch = getchar(); }
structQuery { int l, r, id; booloperator<(const Query& q) const { // 分奇偶排序是常数优化,原理很简单,从左到右再从右到左 if (l / M == q.l / M) return ((l / M) & 1) ? r < q.r : r > q.r; return l < q.l; } } qry[N];
voidadd(int x){ now -= cnt[a[x]] * cnt[a[x]]; cnt[a[x]]++; now += cnt[a[x]] * cnt[a[x]]; }
voidsub(int x){ now -= cnt[a[x]] * cnt[a[x]]; cnt[a[x]]--; now += cnt[a[x]] * cnt[a[x]]; }
signedmain(){ read(n), read(m), read(k); for (int i = 1; i <= n; i++) read(a[i]); for (int i = 1; i <= m; i++) read(qry[i].l), read(qry[i].r), qry[i].id = i; sort(qry+1, qry+1+m);
int l = 1, r = 0; for (int i = 1; i <= m; i++) { while (l > qry[i].l) add(--l); while (r < qry[i].r) add(++r); while (l < qry[i].l) sub(l++); while (r > qry[i].r) sub(r--); ans[qry[i].id] = now; }
for (int i = 1; i <= m; i++) printf("%lld\n", ans[i]);
return0; }
[国家集训队] 小 Z 的袜子
小 Z 把这 N 只袜子从 1 到 N 编号,然后从编号 L 到 R 的袜子中随机选出两只来穿。尽管小 Z 并不在意两只袜子是不是完整的一双,他却很在意袜子的颜色,毕竟穿两只不同色的袜子会很尴尬。
你的任务便是告诉小 Z,他有多大的概率抽到两只颜色相同的袜子。当然,小 Z 希望这个概率尽量高,所以他可能会询问多个 (L,R) 以方便自己选择。
#define int long long constint N = 50010, M = 250; int n, m, now, c[N], cnt[N], ans1[N], ans2[N];
voidread(int& t){ t = 0; char ch = getchar(); while (!isdigit(ch)) ch = getchar(); while (isdigit(ch)) t = t*10 + (ch^48), ch = getchar(); }
structQuery { int l, r, id; booloperator<(const Query& q) const { if (l / M == q.l / M) return ((l / M) & 1) ? r < q.r : r > q.r; return l < q.l; } } qry[N];
intgcd(int a, int b){ if (!b) return a; returngcd(b, a % b); }
intC2(int x){ return x * (x-1) / 2; }
voidadd(int x){ now -= C2(cnt[c[x]]++); now += C2(cnt[c[x]]); }
voidsub(int x){ now -= C2(cnt[c[x]]--); now += C2(cnt[c[x]]); }
signedmain(){ read(n), read(m); for (int i = 1; i <= n; i++) read(c[i]); for (int i = 1; i <= m; i++) read(qry[i].l), read(qry[i].r), qry[i].id = i; sort(qry+1, qry+1+m);
int l = 1, r = 0; for (int i = 1; i <= m; i++) { while (l > qry[i].l) add(--l); while (r < qry[i].r) add(++r); while (l < qry[i].l) sub(l++); while (r > qry[i].r) sub(r--); int a = now, b = C2(qry[i].r - qry[i].l + 1); if (!a || !b) ans1[qry[i].id] = 0, ans2[qry[i].id] = 1; else { int d = gcd(a, b); ans1[qry[i].id] = a / d, ans2[qry[i].id] = b / d; } }
for (int i = 1; i <= m; i++) { printf("%lld/%lld\n", ans1[i], ans2[i]); }
return0; }
[WC2022] 秃子酋长
给定长度为 n 的数列 a,m 次询问 [l,r] 内,排序后相邻的树在原序列中位置差的绝对值之和,保证 ai 互不相同。
#define B(x) ((x - 1) / M + 1) #define lg2highbit(x) (63 - __builtin_clzll(x)) #define lg2lowbit(x) (__builtin_ctzll(x)) typedefunsignedlonglong ull; constint N = 500010, M = 710, G = 4; int n, m, a[N], ra[N], L, R; longlong ans[N], now;
template<typename T = int> inline T read(){ T t = 0; bool neg = 0; char ch = getchar(); while (!isdigit(ch)) neg |= ch == '-', ch = getchar(); while (isdigit(ch)) t = t*10 + (ch^48), ch = getchar(); return neg ? -t : t; }
structTrie { ull* A[G];
Trie() { int sz = 1; for (int i = G-1; i >= 0; i--, sz <<= 6) A[i] = new ull[sz](); }
inlinevoidins(int x){ for (int i = 0; i < G; i++, x >>= 6) { ull mask = 1ull << (x & 63); if (A[i][x >> 6] & mask) return; A[i][x >> 6] |= mask; } }
inlinevoiddel(int x){ for (int i = 0; i < G; i++, x >>= 6) { if (A[i][x >> 6] &= ~(1ull << (x & 63))) return; } }
intpre(int x){ int i, res; for (i = 0; i < G; i++, x >>= 6) { ull s = A[i][x >> 6] & ((1ull << (x & 63)) - 1); if (!s) continue; res = x & ~63 | lg2highbit(s); break; } if (i >= G) return0; for (; i; i--) res = res << 6 | lg2highbit(A[i-1][res]); return res; }
intsuc(int x){ int i, res; for (i = 0; i < G; i++, x >>= 6) { ull s = A[i][x >> 6] & (~((1ull << (x & 63)) - 1) << 1); if (!s) continue; res = x & ~63 | lg2lowbit(s); break; } if (i >= G) return0; for (; i; i--) res = res << 6 | lg2lowbit(A[i-1][res]); return res; }
~Trie() { for (int i = 0; i < G; i++) delete[] A[i]; } } trie;
structQuery { int id, l, r; inlinebooloperator<(const Query& q) const { if (B(l) != B(q.l)) return l < q.l; returnB(l) % 2 ? r > q.r : r < q.r; } } qry[N];
inlinevoidadd(int p){ int pre = trie.pre(a[p]), suc = trie.suc(a[p]); if (pre && suc) now -= abs(ra[suc] - ra[pre]); if (pre) now += abs(p - ra[pre]); if (suc) now += abs(p - ra[suc]); trie.ins(a[p]); }
inlinevoiddel(int p){ trie.del(a[p]); int pre = trie.pre(a[p]), suc = trie.suc(a[p]); if (pre && suc) now += abs(ra[suc] - ra[pre]); if (pre) now -= abs(p - ra[pre]); if (suc) now -= abs(p - ra[suc]); }
intmain(){ n = read(), m = read(); for (int i = 1; i <= n; i++) ra[a[i] = read()] = i; for (int i = 1; i <= m; i++) qry[i].id = i, qry[i].l = read(), qry[i].r = read(); sort(qry+1, qry+1+m);
L = 1, R = 0; for (int i = 1, l, r; i <= m; i++) { l = qry[i].l, r = qry[i].r; while (R < r) add(++R); while (L > l) add(--L); while (R > r) del(R--); while (L < l) del(L++); ans[qry[i].id] = now; }
for (int i = 1; i <= m; i++) printf("%lld\n", ans[i]); return0; }
带修莫队
[国家集训队] 数颜色
墨墨购买了一套 N 支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问。墨墨会向你发布如下指令:
structQuery { int l, r, t, id; booloperator<(const Query& q) const { if (l / M != q.l / M) return l < q.l; if (r / M != q.r / M) return r < q.r; return ((r / M) & 1) ? t < q.t : t > q.t; } } qry[N];
voidadd(int x){ now += !cnt[a[x]]++; }
voidsub(int x){ now -= !--cnt[a[x]]; }
voidupd(int l, int r, int t){ if (l <= pos[t] && pos[t] <= r) sub(pos[t]); swap(a[pos[t]], val[t]); if (l <= pos[t] && pos[t] <= r) add(pos[t]); }
signedmain(){ read(n), read(m); for (int i = 1; i <= n; i++) read(a[i]);
int nqrc = 0, nqry = 0; for (int i = 1; i <= m; i++) { char ch; readalpha(ch); if (ch == 'Q') ++nqry, read(qry[nqry].l), read(qry[nqry].r), qry[nqry].id = nqry, qry[nqry].t = nqrc; else ++nqrc, read(pos[nqrc]), read(val[nqrc]); } sort(qry+1, qry+1+nqry);
int l = 1, r = 0, t = 0; for (int i = 1; i <= nqry; i++) { while (l > qry[i].l) add(--l); while (r < qry[i].r) add(++r); while (l < qry[i].l) sub(l++); while (r > qry[i].r) sub(r--); while (t > qry[i].t) upd(l, r, t--); while (t < qry[i].t) upd(l, r, ++t); ans[qry[i].id] = now; }
for (int i = 1; i <= nqry; i++) printf("%lld\n", ans[i]);
#define eb emplace_back #define int long long constint N = 100010, M = 2200; int n, m, k, now, a[N], cnt[N<<1], ans[N], tot[N]; int pos[N], val[N]; vector<int> nums;
voidread(int& t){ t = 0; char ch = getchar(); while (!isdigit(ch)) ch = getchar(); while (isdigit(ch)) t = t*10 + (ch^48), ch = getchar(); }
structQuery { int l, r, t, id; booloperator<(const Query& q) const { if (l / M != q.l / M) return l < q.l; if (r / M != q.r / M) return r < q.r; return ((r / M) & 1) ? t < q.t : t > q.t; } } qry[N];
voidupd(int l, int r, int t){ if (l <= pos[t] && pos[t] <= r) sub(pos[t]); swap(a[pos[t]], val[t]); if (l <= pos[t] && pos[t] <= r) add(pos[t]); }
signedmain(){ read(n), read(m); for (int i = 1; i <= n; i++) read(a[i]), nums.eb(a[i]);
int nqrc = 0, nqry = 0; for (int i = 1, opt; i <= m; i++) { read(opt); if (opt == 1) ++nqry, read(qry[nqry].l), read(qry[nqry].r), qry[nqry].id = nqry, qry[nqry].t = nqrc; else ++nqrc, read(pos[nqrc]), read(val[nqrc]), nums.eb(val[nqrc]); } sort(qry+1, qry+1+nqry); sort(nums.begin(), nums.end()); nums.erase(unique(nums.begin(), nums.end()), nums.end()); for (int i = 1; i <= n; i++) a[i] = lower_bound(nums.begin(), nums.end(), a[i]) - nums.begin() + 1; for (int i = 1; i <= nqrc; i++) val[i] = lower_bound(nums.begin(), nums.end(), val[i]) - nums.begin() + 1;
int l = 1, r = 0, t = 0; for (int i = 1; i <= nqry; i++) { while (l > qry[i].l) add(--l); while (r < qry[i].r) add(++r); while (l < qry[i].l) sub(l++); while (r > qry[i].r) sub(r--); while (t > qry[i].t) upd(l, r, t--); while (t < qry[i].t) upd(l, r, ++t); int res = 1; while (tot[res] >= 1) res++; ans[qry[i].id] = res; }
for (int i = 1; i <= nqry; i++) printf("%lld\n", ans[i]);
return0; }
树上莫队
Count on a tree II
给定 n 点的树,每个点有颜色,m 询问 a,b 路径上颜色的种类数量。1≤n≤4×104,1≤m≤105。
#define eb emplace_back constint N = 40010, M = 210, K = 20, Q = 100010; int n, m, col[N], fa[N][K], dep[N], L[N], R[N], mark[N], seq[N<<1], idx; int now, ans[Q], cnt[N]; vector<int> cols, g[N];
structQuery { int id, l, r, u; booloperator<(const Query& q) const { if (l / M == q.l / M) return ((l / M) & 1) ? r < q.r : r > q.r; return l < q.l; } } qry[Q];
voidupdate(int u){ mark[u] ^= 1; if (mark[u]) now += !cnt[col[u]]++; else now -= !--cnt[col[u]]; }
voiddfs(int u, int f){ fa[u][0] = f, dep[u] = dep[f] + 1; seq[L[u] = ++idx] = u; for (int k = 1; k < K; k++) fa[u][k] = fa[fa[u][k-1]][k-1]; for (int to: g[u]) if (to != f) dfs(to, u); seq[R[u] = ++idx] = u; }
intlca(int a, int b){ if (dep[a] < dep[b]) swap(a, b); for (int k = K-1; k >= 0; k--) if (dep[fa[a][k]] >= dep[b]) a = fa[a][k]; if (a == b) return a; for (int k = K-1; k >= 0; k--) if (fa[a][k] != fa[b][k]) a = fa[a][k], b = fa[b][k]; return fa[a][0]; }
intmain(){ scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) scanf("%d", &col[i]), cols.eb(col[i]); sort(cols.begin(), cols.end()); for (int i = 1; i <= n; i++) col[i] = lower_bound(cols.begin(), cols.end(), col[i]) - cols.begin(); for (int i = 1, a, b; i < n; i++) scanf("%d%d", &a, &b), g[a].eb(b), g[b].eb(a); dfs(1, 0); for (int i = 1, a, b, u; i <= m; i++) { scanf("%d%d", &a, &b); if (L[a] > L[b]) swap(a, b); u = lca(a, b); if (u == a) qry[i] = {i, L[a], L[b], 0}; else qry[i] = {i, R[a], L[b], u}; } sort(qry+1, qry+1+m);
int l = 1, r = 0; for (int i = 1; i <= m; i++) { while (r > qry[i].r) update(seq[r--]); while (r < qry[i].r) update(seq[++r]); while (l > qry[i].l) update(seq[--l]); while (l < qry[i].l) update(seq[l++]);
if (qry[i].u) update(qry[i].u); ans[qry[i].id] = now; if (qry[i].u) update(qry[i].u); }
for (int i = 1; i <= m; i++) printf("%d\n", ans[i]);
return0; }
[WC2013] 糖果公园
给定 n 点树,每棵树上有一种糖果,共 m 种,第 i 种糖果的美味指数是 Vi,游客第 j 次尝第 i 个糖果增加的权值是 Vi×Wj,q 次询问:
#define int long long #define eb emplace_back constint N = 100010, M = 2160, K = 20; int n, m, q, fa[N][K], dep[N], L[N], R[N], mark[N], seq[N<<1], idx; int now, C[N], W[N], V[N], ans[N], cnt[N]; int pos[N], val[N]; vector<int> g[N];
voidread(int& t){ t = 0; char ch = getchar(); while (!isdigit(ch)) ch = getchar(); while (isdigit(ch)) t = t*10 + (ch^48), ch = getchar(); }
structQuery { int id, l, r, t, u; booloperator<(const Query& q) const { if (l / M != q.l / M) return l < q.l; if (r / M != q.r / M) return r < q.r; return ((r / M) & 1) ? t < q.t : t > q.t; } } qry[N];
voidadd(int u){ now += W[++cnt[C[u]]] * V[C[u]]; }
voidsub(int u){ now -= W[cnt[C[u]]--] * V[C[u]]; }
voidupdate(int u){ mark[u] ^= 1; if (mark[u]) add(u); elsesub(u); }
voidupdtime(int t){ int u = pos[t]; if (mark[u]) sub(u); swap(C[u], val[t]); if (mark[u]) add(u); }
voiddfs(int u, int f){ fa[u][0] = f, dep[u] = dep[f] + 1; seq[L[u] = ++idx] = u; for (int k = 1; k < K; k++) fa[u][k] = fa[fa[u][k-1]][k-1]; for (int to: g[u]) if (to != f) dfs(to, u); seq[R[u] = ++idx] = u; }
intlca(int a, int b){ if (dep[a] < dep[b]) swap(a, b); for (int k = K-1; k >= 0; k--) if (dep[fa[a][k]] >= dep[b]) a = fa[a][k]; if (a == b) return a; for (int k = K-1; k >= 0; k--) if (fa[a][k] != fa[b][k]) a = fa[a][k], b = fa[b][k]; return fa[a][0]; }
signedmain(){ read(n), read(m), read(q); for (int i = 1; i <= m; i++) read(V[i]); for (int i = 1; i <= n; i++) read(W[i]); for (int i = 1, a, b; i < n; i++) read(a), read(b), g[a].eb(b), g[b].eb(a); for (int i = 1; i <= n; i++) read(C[i]); dfs(1, 0);
int qcnt = 0, tcnt = 0; for (int i = 1, opt, a, b, u; i <= q; i++) { read(opt), read(a), read(b); if (opt == 0) ++tcnt, pos[tcnt] = a, val[tcnt] = b; else { ++qcnt; if (L[a] > L[b]) swap(a, b); u = lca(a, b); if (u == a) qry[qcnt] = {qcnt, L[a], L[b], tcnt, 0}; else qry[qcnt] = {qcnt, R[a], L[b], tcnt, u}; } } sort(qry+1, qry+1+qcnt);
int l = 1, t = 0, r = 0; for (int i = 1; i <= qcnt; i++) { while (r > qry[i].r) update(seq[r--]); while (r < qry[i].r) update(seq[++r]); while (l > qry[i].l) update(seq[--l]); while (l < qry[i].l) update(seq[l++]); while (t < qry[i].t) updtime(++t); while (t > qry[i].t) updtime(t--);
if (qry[i].u) update(qry[i].u); ans[qry[i].id] = now; if (qry[i].u) update(qry[i].u); }
for (int i = 1; i <= qcnt; i++) printf("%lld\n", ans[i]);
return0; }
回滚莫队
Mex
给定 n 个元素 a1∼an,m 次询问,每次询问区间内最小没有出现过的自然数,1≤n,m≤2×105,0≤ai≤2×105。
voidresume(int& l){ now = raw, l = rawl; for (int i = 1; i <= idx; i++) ++cnt[a[pos[i]]]; }
voidgetans(int l, int r){ memset(cnt, 0, sizeof cnt); for (int i = l; i <= r; i++) cnt[a[i]]++; for (now = 0; cnt[now]; now++); }
voidsub(int p){ pos[++idx] = p; if (!--cnt[a[p]]) now = min(now, a[p]); }
structQuery { int id, l, r; booloperator<(const Query& q) const { if ((l-1) / M == (q.l-1) / M) return r > q.r; return l < q.l; } } qry[N];
intmain(){ read(n), read(m); for (int i = 1; i <= n; i++) read(a[i]); for (int i = n+1; i < N; i++) a[i] = N-1;
for (int i = 1, l, r; i <= m; i++) read(l), read(r), qry[i] = {i, l, r}; sort(qry+1, qry+1+m);
int l = 114514, r = 0; for (int i = 1; i <= m; i++) { int lblo = (qry[i].l - 1) / M * M + 1; if (l != lblo) getans(l = lblo, r = n); while (r > qry[i].r) sub(r--);
#define int long long #define eb emplace_back constint N = 100010, M = 340; int n, m, now, a[N], ans[N], cnt[N]; int pos[N], raw, rawl, idx; vector<int> nums;
voidread(int& t){ t = 0; char ch = getchar(); while (!isdigit(ch)) ch = getchar(); while (isdigit(ch)) t = t*10 + (ch^48), ch = getchar(); }
intbruteforce(int l, int r){ int res = 0; for (int i = l; i <= r; i++) res = max(res, ++cnt[a[i]] * nums[a[i]]); for (int i = l; i <= r; i++) cnt[a[i]] = 0; return res; }
structQuery { int id, l, r; booloperator<(const Query& q) const { if ((l-1) / M == (q.l-1) / M) return r < q.r; return l < q.l; } } qry[N];
signedmain(){ read(n), read(m); for (int i = 1; i <= n; i++) read(a[i]), nums.eb(a[i]); sort(nums.begin(), nums.end()); for (int i = 1; i <= n; i++) a[i] = lower_bound(nums.begin(), nums.end(), a[i]) - nums.begin();
for (int i = 1, l, r; i <= m; i++) read(l), read(r), qry[i] = {i, l, r}; sort(qry+1, qry+1+m);
int l = 1, r = 1e18; for (int i = 1; i <= m; i++) { int rblo = (qry[i].l - 1) / M * M + M; if (l != rblo+1) r = rblo, l = rblo+1, clear(); // l, r if (qry[i].r <= rblo) ans[qry[i].id] = bruteforce(qry[i].l, qry[i].r); else { while (r < qry[i].r) add(++r); record(l); while (l > qry[i].l) add(--l); ans[qry[i].id] = now; resume(l); } }
for (int i = 1; i <= m; i++) printf("%lld\n", ans[i]); return0; }
最远间隔距离
给定 n 个元素 a1∼an,规定在一个区间内 ai 的权值是 rai−lai,即它最后一次出现的坐标与第一次出现的坐标之差,m 次询问 [l,r] 内的最大权值。1≤n,m≤2×105,1≤a≤2×109。
#define eb emplace_back constint N = 200010, M = 450, INF = 0x3f3f3f3f; int n, m, now, a[N], ans[N], fir[N], las[N]; int pos[N], rawfir[N], rawlas[N], rawans, rawl, idx; vector<int> nums;
voidread(int& t){ t = 0; char ch = getchar(); while (!isdigit(ch)) ch = getchar(); while (isdigit(ch)) t = t*10 + (ch^48), ch = getchar(); }
intbruteforce(int l, int r){ int res = 0; for (int i = l; i <= r; i++) { fir[a[i]] = min(fir[a[i]], i); res = max(res, i - fir[a[i]]); } for (int i = l; i <= r; i++) fir[a[i]] = INF; return res; }
structQuery { int id, l, r; booloperator<(const Query& q) const { if ((l-1) / M == (q.l-1) / M) return r < q.r; return l < q.l; } } qry[N];
signedmain(){ read(n); for (int i = 1; i <= n; i++) read(a[i]), nums.eb(a[i]); sort(nums.begin(), nums.end()); nums.erase(unique(nums.begin(), nums.end()), nums.end()); for (int i = 1; i <= n; i++) a[i] = lower_bound(nums.begin(), nums.end(), a[i]) - nums.begin(); read(m); for (int i = 1, l, r; i <= m; i++) read(l), read(r), qry[i] = {i, l, r}; sort(qry+1, qry+1+m);
int l = 1, r = N; for (int i = 1; i <= m; i++) { int rblo = (qry[i].l - 1) / M * M + M; if (l != rblo+1) r = rblo, l = rblo+1, clear(); if (qry[i].r <= rblo) ans[qry[i].id] = bruteforce(qry[i].l, qry[i].r); else { while (r < qry[i].r) addr(++r); record(l); while (l > qry[i].l) addl(--l); ans[qry[i].id] = now; resume(l); } }
for (int i = 1; i <= m; i++) printf("%d\n", ans[i]); return0; }
typedefunsignedlonglong ull; constint N = 100010, G = 4, M = 320, INF = 2e9; vector<int> nums; int n, q, a[N], ans[N], L, R, now;
inlinevoidread(int& t){ t = 0; char ch = getchar(); while (!isdigit(ch)) ch = getchar(); while (isdigit(ch)) t = t*10 + (ch-'0'), ch = getchar(); }
inlinevoidwrite(int t){ staticchar stk[20]; int tp = 0; while (t) stk[++tp] = (t % 10) + '0', t /= 10; while (tp) putchar(stk[tp--]); }
structQuery { int id, l, r;
booloperator<(const Query& Q) const { if (B(l) == B(Q.l)) return r < Q.r; return l < Q.l; } } qry[N];
structTrie { ull* A[G];
Trie() { int sz = 1; for (int i = G-1; i >= 0; i--, sz <<= 6) A[i] = new ull[sz](); }
voidclear(){ int sz = 1; for (int i = G-1; i >= 0; i--, sz <<= 6) memset(A[i], 0, sz * sizeof(ull)); }
voidins(int x){ for (int i = 0; i < G; i++, x >>= 6) { ull mask = 1ull << (x & 63); if (A[i][x >> 6] & mask) return; A[i][x >> 6] |= mask; } }
voiddel(int x){ for (int i = 0; i < G; i++, x >>= 6) { if (A[i][x >> 6] &= ~(1ull << (x & 63))) return; } }
intpre(int x){ int i, res = 0; for (i = 0; i < G; i++, x >>= 6) { ull s = A[i][x >> 6] & ((1ull << (x & 63)) - 1); if (!s) continue; res = x & ~63 | lg2highbit(s); break; } if (i >= G) return0; for (; i; i--) res = res << 6 | lg2highbit(A[i-1][res]); return res; }
intsuc(int x){ int i, res = 0; for (i = 0; i < G; i++, x >>= 6) { ull s = A[i][x >> 6] & (~((1ull << (x & 63)) - 1) << 1); if (!s) continue; res = x & ~63 | lg2lowbit(s); break; } if (i >= G) return0; for (; i; i--) res = res << 6 | lg2lowbit(A[i-1][res]); return res; }
~Trie() { for (int i = 0; i < G; i++) delete[] A[i]; } } force, trie;
intbruteforce(int l, int r){ int res = INF; for (int i = l, pre, suc; i <= r; i++) { force.ins(a[i]), pre = force.pre(a[i]), suc = force.suc(a[i]); if (pre) res = min(res, nums[a[i]] - nums[pre]); if (suc) res = min(res, nums[suc] - nums[a[i]]); } for (int i = l; i <= r; i++) force.del(a[i]); return res; }
voidadd(int p){ stk[++tp] = a[p]; trie.ins(a[p]); int pre = trie.pre(a[p]), suc = trie.suc(a[p]); if (pre) now = min(now, nums[a[p]] - nums[pre]); if (suc) now = min(now, nums[suc] - nums[a[p]]); }
voidresume(){ L = rawl, now = rawnow; while (tp) trie.del(stk[tp--]); }
intmain(){ read(n), read(q); nums.reserve(n+1); nums.eb(-1); for (int i = 1; i <= n; i++) read(a[i]), nums.eb(a[i]); sort(nums.begin(), nums.end()); for (int i = 1; i <= n; i++) a[i] = lower_bound(nums.begin(), nums.end(), a[i]) - nums.begin(); force.clear();
for (int i = 1; i <= q; i++) qry[i].id = i, read(qry[i].l), read(qry[i].r); sort(qry+1, qry+1+q);
for (int i = 1, l, r, rbl; i <= q; i++) { l = qry[i].l, r = qry[i].r, rbl = (B(l) - 1) * M + M; if (L != rbl+1) trie.clear(), L = rbl+1, R = rbl, now = INF; if (r <= rbl) ans[qry[i].id] = bruteforce(l, r); else { while (R < r) add(++R); record(); while (L > l) add(--L); ans[qry[i].id] = now; resume(); } }
for (int i = 1; i <= q; i++) write(ans[i]), putchar('\n'); return0; }
Q1.reserve(m), Q2.reserve(m); for (int i = 1; i <= n; i++) read(a[i]); for (int i = 0; i < (1<<14); i++) if (__builtin_popcount(i) == k) numsA.pb(i); for (int i = 1; i <= n; i++) { g[i] = g[i-1] + f[a[i]]; for (int x: numsA) f[a[i] ^ x]++; } memset(f, 0, sizeof f); for (int i = n; i; i--) { g1[i] = g1[i+1] + f[a[i]]; for (int x: numsA) f[a[i] ^ x]++; } for (int i = 1; i <= m; i++) read(Q[i].l), read(Q[i].r), Q[i].id = i; sort(Q+1, Q+1+m);
int l = 1, r = 0; for (int i = 1; i <= m; i++) { int L = Q[i].l, R = Q[i].r, id = Q[i].id; if (r < R) ans[id] += g[R] - g[r], Q1.pb({id, l-1, r+1, R, -1}); if (r > R) ans[id] -= g[r] - g[R], Q1.pb({id, l-1, R+1, r, 1}); r = R; if (l > L) ans[id] += g1[L] - g1[l], Q2.pb({id, r+1, L, l-1, -1}); if (l < L) ans[id] -= g1[l] - g1[L], Q2.pb({id, r+1, l, L-1, 1}); l = L; } sort(Q1.begin(), Q1.end(), incq); sort(Q2.begin(), Q2.end(), decq);
int p = 0; memset(f, 0, sizeof f); for (constauto& q: Q1) { while (p < q.p) { ++p; for (int x: numsA) f[a[p] ^ x]++; } for (int i = q.a; i <= q.b; i++) ans[q.id] += f[a[i]] * q.t; }
memset(f, 0, sizeof f); p = n+1; for (constauto& q: Q2) { while (p > q.p) { --p; for (int x: numsA) f[a[p] ^ x]++; } for (int i = q.a; i <= q.b; i++) ans[q.id] += f[a[i]] * q.t; } for (int i = 2; i <= m; i++) ans[Q[i].id] += ans[Q[i-1].id]; for (int i = 1; i <= m; i++) printf("%lld\n", ans[i]); return0; }
#define lowbit(x) ((x)&(-x)) #define int long long #define pb push_back #define B(x) ((x-1) / M + 1) constint N = 100010, M = 340; int n, m, ans[N], a[N], g[N], g1[N];
voidread(int& t){ t = 0; char ch = getchar(); while (!isdigit(ch)) ch = getchar(); while (isdigit(ch)) t = t*10 + (ch^48), ch = getchar(); }
voidadd(int l, int r, int x){ if (B(l) == B(r)) { for (int i = l; i <= r; i++) val[i] += x; return; } int L = l, R = r; while (B(L) == B(l)) val[L++] += x; while (B(R) == B(r)) val[R--] += x; for (int p = B(L); p <= B(R); p++) tag[p] += x; }
voidadd(int p, int x){ for (; p < N; p += lowbit(p)) tr[p] += x; }
intquery(int p){ int res = 0; for (; p; p -= lowbit(p)) res += tr[p]; return res; }
voidadd(int l, int r, int x){ add(l, x); add(r+1, -x); } } bit;
structQuery { int id, l, r; booloperator<(const Query& q) const { if (l / M != q.l / M) return l < q.l; return ((l / M) & 1) ? r < q.r : r > q.r; } } Q[N];
vector<int> nums; signedmain(){ read(n), read(m); nums.reserve(n); for (int i = 1; i <= n; i++) read(a[i]), nums.pb(a[i]); sort(nums.begin(), nums.end()); for (int i = 1; i <= n; i++) a[i] = lower_bound(nums.begin(), nums.end(), a[i]) - nums.begin() + 1; for (int i = 1; i <= m; i++) Q[i].id = i, read(Q[i].l), read(Q[i].r); sort(Q+1, Q+1+m);
// bit.init(); for (int i = 1; i <= n; i++) { g[i] = g[i-1] + bit.query(a[i]); if (a[i] > 1) bit.add(1, a[i]-1, 1); }
bit.init(); for (int i = n; i; i--) { g1[i] = g1[i+1] + bit.query(a[i]); bit.add(a[i]+1, 1); }
int l = 1, r = 0; for (int i = 1; i <= m; i++) { int L = Q[i].l, R = Q[i].r, id = Q[i].id; if (r < R) ans[id] += g[R] - g[r], Q1.pb({id, l-1, r+1, R, -1}); if (r > R) ans[id] -= g[r] - g[R], Q1.pb({id, l-1, R+1, r, 1}); r = R; if (l > L) ans[id] += g1[L] - g1[l], Q2.pb({id, r+1, L, l-1, -1}); if (l < L) ans[id] -= g1[l] - g1[L], Q2.pb({id, r+1, l, L-1, 1}); l = L; }
int p = 0; // blo.init(); for (constauto& q: Q1) { while (p < q.p) blo.add(0, a[++p]-1, 1); for (int i = q.a; i <= q.b; i++) ans[q.id] += blo.query(a[i]) * q.t; }
p = n+1; blo.init(); for (constauto& q: Q2) { while (p > q.p) blo.add(a[--p]+1, n+1, 1); for (int i = q.a; i <= q.b; i++) ans[q.id] += blo.query(a[i]) * q.t; }
for (int i = 2; i <= m; i++) ans[Q[i].id] += ans[Q[i-1].id]; for (int i = 1; i <= m; i++) printf("%lld\n", ans[i]);