1. 程式人生 > >3781. 小B的詢問【莫隊】

3781. 小B的詢問【莫隊】

turn 其中 包含 output sigma 共有m個 pre stream tdi

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

莫隊水題

 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\n",Ask[i].ans); 55 }

3781. 小B的詢問【莫隊】