您的位置:首页 > 其它

bzoj3781: 小B的询问

2015-08-02 17:40 302 查看

Description

小B有一个序列,包含N个1~K之间的整数。他一共有M个询问,每个询问给定一个区间[L..R],求Sigma(c(i)^2)的值,其中i的值从1到K,其中c(i)表示数字i在[L..R]中的重复次数。小B请你帮助他回答询问。

Input

第一行,三个整数N、M、K。
第二行,N个整数,表示小B的序列。
接下来的M行,每行两个整数L、R。

Output

M行,每行一个整数,其中第i行的整数表示第i个询问的答案。

Sample Input

6 4 3
1 3 2 1 1 3
1 4
2
6
3 5
5 6

Sample Output

6
9
5
2

HINT

对于全部的数据,1<=N、M、K<=50000

莫队裸题······
code:

#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
#define maxn 50005
using namespace std;
typedef long long int64;
char ch;
int n,m,k,a[maxn],cnt[maxn],pos[maxn],siz;
int64 ans[maxn],tmp;
struct query{
int l,r,id;
}list[maxn];
bool cmp(query a,query b){
if (pos[a.l]!=pos[b.l]) return pos[a.l]<pos[b.l];
return pos[a.r]<pos[b.r];
}
bool ok;
void read(int &x){
for (ok=0,ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') ok=1;
for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar());
if (ok) x=-x;
}
void modify(int col,int op){
tmp-=(1LL*cnt[col]*cnt[col]);
cnt[col]+=op;
tmp+=(1LL*cnt[col]*cnt[col]);
}
void work(){
int l=1,r=0;
for (int i=1;i<=m;i++){
for (;r<list[i].r;r++) modify(a[r+1],1);
for (;r>list[i].r;r--) modify(a[r],-1);
for (;l<list[i].l;l++) modify(a[l],-1);
for (;l>list[i].l;l--) modify(a[l-1],1);
ans[list[i].id]=tmp;
}
}
int main(){
read(n),read(m),read(k),siz=(int)sqrt(n);
for (int i=1;i<=n;i++) read(a[i]);
for (int i=1;i<=n;i++) pos[i]=i/siz;
for (int i=1;i<=m;i++) read(list[i].l),read(list[i].r),list[i].id=i;
sort(list+1,list+m+1,cmp);
work();
for (int i=1;i<=m;i++) printf("%lld\n",ans[i]);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: