题目:https://ac.2333.moe/Problem/view.xhtml?id=1457
题意:给定一个数组,然后给出一些询问区间,求区间内每个数出现次数的立方和
思路:莫队算法模板题。注意要离散化数据
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long ll;
const int N = 100010;
struct node
{
int l, r, id;
} g[N];
int n, m, unit;
int a[N], b[N], num[N];
ll tmp, res[N];
bool cmp(node a, node b)
{
return a.l/unit != b.l/unit ? a.l/unit < b.l/unit :a.r < b.r;
}
void add(int i)
{
tmp -= (ll)num[i] * num[i] * num[i];
num[i]++;
tmp += (ll)num[i] * num[i] * num[i];
}
void del(int i)
{
tmp -= (ll)num[i] * num[i] * num[i];
num[i]--;
tmp += (ll)num[i] * num[i] * num[i];
}
void solve()
{
unit = (int)sqrt(1.0*n);
sort(g+1, g+1+m, cmp);
memset(num, 0, sizeof num);
int l = 1, r = 0;
tmp = 0;
for(int i = 1; i <= m; i++)
{
while(r < g[i].r) add(a[++r]);
while(r > g[i].r) del(a[r--]);
while(l < g[i].l) del(a[l++]);
while(l > g[i].l) add(a[--l]);
res[g[i].id] = tmp;
}
for(int i = 1; i <= m; i++) printf("%I64d\n", res[i]);
}
int main()
{
while(~ scanf("%d", &n))
{
for(int i = 1; i <= n; i++) scanf("%d", &a[i]), b[i] = a[i];
sort(b+1, b+1+n);
for(int i = 1; i <= n; i++) a[i] = lower_bound(b+1, b+1+n, a[i]) - b;
scanf("%d", &m);
for(int i = 1; i <= m; i++) scanf("%d%d", &g[i].l, &g[i].r), g[i].id = i;
solve();
}
return 0;
}