bzoj3781: 小B的询问

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:
 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<algorithm>
 6 #define maxn 50005
 7 using namespace std;
 8 typedef long long int64;
 9 char ch;
10 int n,m,k,a[maxn],cnt[maxn],pos[maxn],siz;
11 int64 ans[maxn],tmp;
12 struct query{
13     int l,r,id;
14 }list[maxn];
15 bool cmp(query a,query b){
16     if (pos[a.l]!=pos[b.l]) return pos[a.l]<pos[b.l];
17     return pos[a.r]<pos[b.r];
18 }
19 bool ok;
20 void read(int &x){
21     for (ok=0,ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') ok=1;
22     for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar());
23     if (ok) x=-x;
24 }
25 void modify(int col,int op){
26     tmp-=(1LL*cnt[col]*cnt[col]);
27     cnt[col]+=op;
28     tmp+=(1LL*cnt[col]*cnt[col]);    
29 }
30 void work(){
31     int l=1,r=0;
32     for (int i=1;i<=m;i++){
33         for (;r<list[i].r;r++) modify(a[r+1],1);
34         for (;r>list[i].r;r--) modify(a[r],-1);
35         for (;l<list[i].l;l++) modify(a[l],-1);
36         for (;l>list[i].l;l--) modify(a[l-1],1);
37         ans[list[i].id]=tmp;
38     }
39 }
40 int main(){
41     read(n),read(m),read(k),siz=(int)sqrt(n);
42     for (int i=1;i<=n;i++) read(a[i]);
43     for (int i=1;i<=n;i++) pos[i]=i/siz;
44     for (int i=1;i<=m;i++) read(list[i].l),read(list[i].r),list[i].id=i;
45     sort(list+1,list+m+1,cmp);
46     work();
47     for (int i=1;i<=m;i++) printf("%lld\n",ans[i]);
48     return 0;
49 }

 

posted @ 2015-08-02 17:40  chenyushuo  阅读(183)  评论(0编辑  收藏  举报