[CF86D] Powerful array - 莫队
Description
给定长度为 \(n\) 的序列 \(a\),有 \(q\) 次询问,每次询问给出两个数 \(l,r\)。对于每次询问,设 \(cnt_i\) 表示 \(i\) 在 \(a_l,a_{l+1},\cdots,a_r\) 出现的次数,您需要求出 \(\displaystyle\sum_i cnt_i^2\cdot i\)。\(1\le a_i\le 10^6\)
Solution
这种区间问题很显然就是莫队了,每次修改的时候我们减去原来的答案再加上新的
可能因为用了太多 vector 被卡常了,于是加了个奇偶交换
#include <bits/stdc++.h>
using namespace std;
#define int long long
vector<int> belong;
struct MoSolution
{
vector<int> a;
int block_size;
struct Question
{
int l, r, id;
friend bool operator<(const Question &lhs, const Question &rhs)
{
if (belong[lhs.l] == belong[rhs.l])
if (belong[lhs.l] & 1)
return lhs.r < rhs.r;
else
return lhs.r > rhs.r;
else
return lhs.l < rhs.l;
}
};
vector<Question> questions;
struct Bucket
{
static const int maxn = 1e6 + 5;
vector<int> cnt;
int ans;
Bucket()
{
cnt.resize(maxn);
ans = 0;
}
void Add(int x)
{
ans += 2 * cnt[x] * x + x;
cnt[x]++;
}
void Dec(int x)
{
cnt[x]--;
ans -= 2 * cnt[x] * x + x;
}
} bucket;
vector<int> ans;
int n, m;
void solve()
{
cin >> n >> m;
block_size = sqrt(n);
a.resize(n + 2);
belong.resize(n + 2);
for (int i = 1; i <= n; i++)
cin >> a[i];
for (int i = 1; i <= n; i++)
belong[i] = i / block_size;
questions.resize(m + 2);
ans.resize(m + 2);
for (int i = 1; i <= m; i++)
{
cin >> questions[i].l >> questions[i].r;
questions[i].id = i;
}
sort(&questions[1], &questions[m + 1]);
int l = 1, r = 0;
for (int i = 1; i <= m; i++)
{
int ql = questions[i].l, qr = questions[i].r;
while (r < qr)
bucket.Add(a[++r]);
while (l > ql)
bucket.Add(a[--l]);
while (r > qr)
bucket.Dec(a[r--]);
while (l < ql)
bucket.Dec(a[l++]);
ans[questions[i].id] = bucket.ans;
}
for (int i = 1; i <= m; i++)
{
cout << ans[i] << endl;
}
}
};
signed main()
{
MoSolution solution;
solution.solve();
}