洛谷 P2709 小B的询问
洛谷 P2709 小B的询问
题目描述
小B 有一个长为 nnn 的整数序列 aaa,值域为 [1,k][1,k][1,k]。
他一共有 mmm 个询问,每个询问给定一个区间 [l,r][l,r][l,r],求:
∑i=1kci2\sum\limits_{i=1}^k c_i^2 i=1∑kci2
其中 cic_ici 表示数字 iii 在 [l,r][l,r][l,r] 中的出现次数。
小B请你帮助他回答询问。
输入格式
第一行三个整数 n,m,kn,m,kn,m,k。
第二行 nnn 个整数,表示 小B 的序列。
接下来的 mmm 行,每行两个整数 l,rl,rl,r。
输出格式
输出 mmm 行,每行一个整数,对应一个询问的答案。
题解:
莫队普通的裸题。
作为莫队入门题使用。
代码:
#include<cstdio>
#include<cmath>
#include<algorithm>
#define int long long
using namespace std;
const int maxn=5e4+4;
int n,m,k;
int a[maxn],b[maxn];
int cnt[maxn],ans[maxn];
struct node
{
int l,r,id,pos;
}q[maxn];
bool cmp(node x,node y)
{
if(x.pos==y.pos)
return x.r<y.r;
return x.pos<y.pos;
}
signed main()
{
scanf("%lld%lld%lld",&n,&m,&k);
int block=sqrt(n);
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
b[i]=(i-1)/block+1;
}
for(int i=1;i<=m;i++)
{
scanf("%lld%lld",&q[i].l,&q[i].r);
q[i].id=i;
q[i].pos=b[q[i].l];
}
sort(q+1,q+m+1,cmp);
int l=1,r=0;
int tmp=0;
for(int i=1;i<=m;i++)
{
while(l>q[i].l)
l--,cnt[a[l]]++,tmp+=(2*cnt[a[l]]-1);
while(r<q[i].r)
r++,cnt[a[r]]++,tmp+=(2*cnt[a[r]]-1);
while(l<q[i].l)
cnt[a[l]]--,tmp-=(2*cnt[a[l]]+1),l++;
while(r>q[i].r)
cnt[a[r]]--,tmp-=(2*cnt[a[r]]+1),r--;
ans[q[i].id]=tmp;
}
for(int i=1;i<=m;i++)
printf("%lld\n",ans[i]);
return 0;
}