D. Powerful array
D. Powerful array
题意
给定一个数列:a[i] (1<= i <= n) K[j]表示 在区间 [l,r]中j出现的次数。有t个查询,每个查询l,r,对区间内所有a[i],求sigma(K[a[i]] * K[a[i]] * a[i])。
分析
首先将区间分块,每块sqrt(n)个,先读入所有的查询,对查询进行排序:先按块序号从小到大,再按右端点的值从小大到排序。
按顺序读入查询,动态变更区间,以及区间的值。如果某个点出现了 x 次,出现 x + 1 次时,区间内增加(2 * x + 1) 。
跑了3000多ms,果然很暴力。
code
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 1e6 + 5;
const int MAXT = 2e5 + 10;
ll a[MAXN];
ll cnt[MAXN];
ll ans[MAXT];
int L, R;
ll res;
struct node
{
int l, r, bid, id;
bool operator < (const node &other) const
{
if(other.bid == bid) return r < other.r;
return bid < other.bid;
}
}q[MAXT];
void query(int l, int r, int is)
{
if(is)
{
for(int i = l; i < L; i++)
{
res += ((cnt[a[i]] << 1) + 1) * a[i];
cnt[a[i]]++;
}
for(int i = R + 1; i <= r; i++)
{
res += ((cnt[a[i]] << 1) + 1) * a[i];
cnt[a[i]]++;
}
for(int i = L; i < l; i++)
{
cnt[a[i]]--;
res -= ((cnt[a[i]] << 1) + 1) * a[i];
}
for(int i = r + 1; i <= R; i++)
{
cnt[a[i]]--;
res -= ((cnt[a[i]] << 1) + 1) * a[i];
}
}
else
{
for(int i = l; i <= r; i++)
{
res += ((cnt[a[i]] << 1) + 1) * a[i];
cnt[a[i]]++;
}
}
L = l; R = r;
ans[q[is].id] = res;
}
int main()
{
int n, t;
scanf("%d%d", &n, &t);
int bsize = sqrt(n + 1);
for(int i = 1; i <= n; i++) scanf("%I64d", &a[i]);
for(int i = 0; i < t; i++)
{
scanf("%I64d%I64d", &q[i].l, &q[i].r);
q[i].bid = q[i].l / bsize;
q[i].id = i;
}
sort(q, q + t);
for(int i = 0; i < t; i++) query(q[i].l, q[i].r, i);
for(int i = 0; i < t; i++) printf("%I64d\n", ans[i]);
return 0;
}