[洛谷P2709]小B的询问
题目传送门
这道题的解法是莫队。莫队是一个离线的算法(也可以在线),能满足$O(1)$转移的算法。通过分块来获得适当的求解顺序使得复杂度控制在$O(n\sqrt{n})$。
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 #define re register 6 #define rep(i, a, b) for (re int i = a; i <= b; ++i) 7 #define repd(i, a, b) for (re int i = a; i >= b; --i) 8 #define maxx(a, b) a = max(a, b); 9 #define minn(a, b) a = min(a, b); 10 #define LL long long 11 #define INF (1 << 30) 12 13 inline int read() { 14 int w = 0, f = 1; char c = getchar(); 15 while (!isdigit(c)) f = c == '-' ? -1 : f, c = getchar(); 16 while (isdigit(c)) w = (w << 3) + (w << 1) + (c ^ '0'), c = getchar(); 17 return w * f; 18 } 19 20 const int maxn = 50000 + 5; 21 22 struct Block { 23 int l, r, pos, id, ans; 24 } q[maxn]; 25 bool cmp1(Block a, Block b) { return a.pos < b.pos || a.pos == b.pos && a.r < b.r; } 26 bool cmp2(Block a, Block b) { return a.id < b.id; } 27 int sqr(int a) { return a*a; } 28 29 int n, m, k, a[maxn], size, cnt[maxn], ans = 0; 30 31 int main() { 32 n = read(), m = read(), k = read(); 33 size = sqrt(n); 34 rep(i, 1, n) 35 a[i] = read(); 36 37 rep(i, 1, m) q[i].l = read(), q[i].r = read(), q[i].id = i, q[i].pos = (q[i].l+size-1) / size; 38 sort(q+1, q+m+1, cmp1); 39 40 int pl = 1, pr = 0; 41 rep(i, 1, m) { 42 while (pl < q[i].l) ans -= 2 * cnt[a[pl]] - 1, cnt[a[pl++]]--; 43 while (pl > q[i].l) cnt[a[--pl]]++, ans += 2 * cnt[a[pl]] - 1; 44 while (pr < q[i].r) cnt[a[++pr]]++, ans += 2 * cnt[a[pr]] - 1; 45 while (pr > q[i].r) ans -= 2 * cnt[a[pr]] - 1, cnt[a[pr--]]--; 46 q[i].ans = ans; 47 } 48 sort(q+1, q+m+1, cmp2); 49 rep(i, 1, m) printf("%d\n", q[i].ans); 50 51 return 0; 52 }