[洛谷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 }

 

posted @ 2019-02-13 21:32  AC-Evil  阅读(142)  评论(0编辑  收藏  举报