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

 

裸莫队算法。BZOJ权限题,未评测。

 1 /*by SilverN*/
 2 #include<algorithm>
 3 #include<iostream>
 4 #include<cstring>
 5 #include<cstdio>
 6 #include<cmath>
 7 #define LL long long
 8 using namespace std;
 9 const int mxn=100001;
10 int read(){
11     int x=0,f=1;char ch=getchar();
12     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
13     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
14     return x*f;
15 }
16 struct line{
17     int l,r;
18     int q;
19     int id;
20 }a[mxn];
21 int cmp(const line a,const line b){
22     if(a.q==b.q)return a.r<b.r;
23     return a.q<b.q;
24 }
25 int n,m,k;
26 int c[mxn];
27 LL cnt[mxn],ans[mxn];
28 int main(){
29     int i,j;
30     n=read();m=read();k=read();
31     for(i=1;i<=n;i++) c[i]=read();
32     int size=sqrt(n);//分块 
33     for(i=1;i<=m;i++){
34         a[i].l=read();
35         a[i].r=read();
36         a[i].id=i;
37         a[i].q=(a[i].l-1)/size+1;
38     }
39     sort(a+1,a+m+1,cmp);
40     int l=1,r=0;
41     LL res=0;
42     for(i=1;i<=m;i++){
43         while(l>a[i].l){
44             l--;cnt[c[l]]++;res+=2*cnt[c[l]]-1;//相当于(n+1)*(n+1)-n*n
45         }
46         while(r<a[i].r){
47             r++;cnt[c[r]]++;res+=2*cnt[c[r]]-1;
48         }
49         while(l<a[i].l){
50             cnt[c[l]]--;res-=2*cnt[c[l]]+1;l++;
51         }
52         while(r>a[i].r){
53             cnt[c[r]]--;res-=2*cnt[c[r]]+1;r--;
54         }
55         ans[a[i].id]=res;
56     }
57     for(i=1;i<=m;i++)printf("%lld\n",ans[i]);
58     return 0;
59 }

 

posted @ 2016-09-12 15:39  SilverNebula  阅读(181)  评论(0编辑  收藏  举报
AmazingCounters.com