莫队算法可以一个可高效解决绝大多数离线+无修改+区间查询问题的算法。这类问题具体是指:如果知道[L,R]的答案时,可以在 O(g(n))的时间下得到[L,R−1],[L,R+1],[L−1,R],[L+1,R]的答案的话,就可以$O(n\sqrt n · \mathrm{g}(n))$的时间内求出所有查询。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #define N 50010 #define LL long long usingnamespace std; int n, m, k, unit; structMo { int l; int r; int id; int pos; booloperator<(const Mo &rhs) const { if (pos == rhs.pos) return r < rhs.r; else return l < rhs.l; } } a[N]; int b[N], cnt[N]; LL Ans[N]; intmain() { scanf("%d%d%d", &n, &m, &k); unit = sqrt(n + 1); for (int i = 1; i <= n; i++) scanf("%d", &b[i]); for (int i = 1; i <= m; i++) { scanf("%d%d", &a[i].l, &a[i].r); a[i].id = i; a[i].pos = a[i].l / unit; } sort(a + 1, a + 1 + m); int l = 1, r = 0; LL ans = 0; for (int i = 1; i <= m; i++) { while (l > a[i].l) { l--; //操作 ans += } while (r < a[i].r) { r++; //操作 ans += } while (l < a[i].l) { ans -= //操作 l++; } while (r > a[i].r) { ans -= //操作 r--; } Ans[a[i].id] = ans; } for (int i = 1; i <= m; i++) printf("%lld\n", Ans[i]); return0; }