Codeforces 86D Powerful array (莫队算法)
题目链接 Powerful array
给你n个数,m次询问,Ks为区间内s的数目,求区间[L,R]之间所有Ks*Ks*s的和。
$1<=n,m<=200000, 1<=s<=10^{6}$
考虑莫队算法
把区间排序,然后让l和r分别询问即可。
根据排序的方式,l指针和r指针移动次数和大概是$n\sqrt{n}$ 级别的。
#include <bits/stdc++.h> using namespace std; #define rep(i, a, b) for (int i(a); i <= (b); ++i) #define dec(i, a, b) for (int i(a); i >= (b); --i) typedef long long LL; const int N = 2e5 + 10; const int M = 1e6 + 10; int belong[N]; struct query{ int l, r; int id; void scan(){ scanf("%d%d", &l, &r); } friend bool operator < (const query &a, const query &b){ return belong[a.l] == belong[b.l] ? a.r < b.r : belong[a.l] < belong[b.l]; } } q[N]; int n, m; int a[N], c[M]; int BS, l, r; LL ret[N], ans; int main(){ scanf("%d%d", &n, &m); rep(i, 1, n) scanf("%d", a + i); BS = sqrt(n); rep(i, 1, n) belong[i] = (i - 1) / BS + 1; rep(i, 1, m){ q[i].scan(); q[i].id = i; } sort(q + 1, q + m + 1); l = 0; r = 0; ans = 0; rep(i, 1, m){ while (l > q[i].l){ --l; ans += (LL)(2 * c[a[l]] + 1) * a[l]; ++c[a[l]]; } while (r < q[i].r){ ++r; ans += (LL)(2 * c[a[r]] + 1) * a[r]; ++c[a[r]]; } while (l < q[i].l){ --c[a[l]]; ans -= (LL)(2 * c[a[l]] + 1) * a[l]; ++l; } while (r > q[i].r){ --c[a[r]]; ans -= (LL)(2 * c[a[r]] + 1) * a[r]; --r; } ret[q[i].id] = ans; } rep(i, 1, m) printf("%lld\n", ret[i]); return 0; }