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

Solution

莫队水题

Code

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<algorithm>
 5 #include<cmath>
 6 #define N (50000+100)
 7 using namespace std;
 8 struct node
 9 {
10     int l,r,id,ans,ord;
11 }Ask[N];
12 int a[N],n,m,k,cnt[N],Sigma,l=1,r=0;
13 bool cmp1 (node a,node b){return a.id==b.id?a.r<b.r:a.id<b.id;}
14 bool cmp2 (node a,node b){return a.ord<b.ord;}
15 
16 void Ins(int x)
17 {
18     Sigma-=cnt[x]*cnt[x];
19     cnt[x]++;
20     Sigma+=cnt[x]*cnt[x];
21 }
22 void Del(int x)
23 {
24     Sigma-=cnt[x]*cnt[x];
25     cnt[x]--;
26     Sigma+=cnt[x]*cnt[x];
27 }
28 void MoQueue(int x)
29 {
30     int L=Ask[x].l,R=Ask[x].r;
31     while (l<L) Del(a[l++]);
32     while (l>L) Ins(a[--l]);
33     while (r<R) Ins(a[++r]);
34     while (r>R) Del(a[r--]);
35     Ask[x].ans=Sigma;
36 }
37 int main()
38 {
39     scanf("%d%d%d",&n,&m,&k);
40     int len=pow(n,2.0/3.0);
41     for (int i=1;i<=n;++i) 
42         scanf("%d",&a[i]);
43     for (int i=1;i<=m;++i)
44     {
45         scanf("%d%d",&Ask[i].l,&Ask[i].r);
46         Ask[i].id=Ask[i].l/len;
47         Ask[i].ord=i;
48     }
49     sort(Ask+1,Ask+m+1,cmp1);
50     for (int i=1;i<=m;++i)
51         MoQueue(i);
52     sort(Ask+1,Ask+m+1,cmp2);
53     for (int i=1;i<=m;++i)
54         printf("%d
",Ask[i].ans);
55 }
原文地址:https://www.cnblogs.com/refun/p/8685605.html