Time Limit: 10 Sec Memory Limit: 128 MB Submit: 942 Solved: 635
Description
小B有一个序列,包含N个1~K之间的整数。他一共有M个询问,每个询问给定一个区间[L..R],求Sigma(c(i)^2)的值,其中i的值从1到K,其中c(i)表示数字i在[L..R]中的重复次数。小B请你帮助他回答询问。
第一行,三个整数N、M、K。
第二行,N个整数,表示小B的序列。
接下来的M行,每行两个整数L、R。
Output
M行,每行一个整数,其中第i行的整数表示第i个询问的答案。
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
Source
题解:
显然就是一道裸莫队,裸到不能再裸…我们可以称其为,没有穿衣服的莫队算法
/
**************************************************************
Problem:
3781
User: cdqz_hhl
Language: C++
Result: Accepted
Time:
1688 ms
Memory:
3060 kb
****************************************************************/
const
int MAXN=
50005;
using namespace std;
int n,
m,K,len;
int b[MAXN];
long long cnt[MAXN],final[MAXN];
struct Question{
int l,r,loc,id;
}
q[MAXN];
bool cmp(const Question& A,const Question& B){
if(A.loc==B.loc)
return A.r<B.r;
else return A.loc<B.loc;
}
void solve(){
sort(
q+
1,
q+
m+
1,cmp);
int l=
1,r=
0;long long temp=
0;
for(register
int i=
1;i<=
m;i++){
while(l>
q[i].l)l--,cnt[b[l]]++,temp+=
2*cnt[b[l]]-
1;
while(r<
q[i].r)r++,cnt[b[r]]++,temp+=
2*cnt[b[r]]-
1;
while(l<
q[i].l)cnt[b[l]]--,temp-=
2*cnt[b[l]]+
1,l++;
while(r>
q[i].r)cnt[b[r]]--,temp-=
2*cnt[b[r]]+
1,r--;
final[
q[i].id]=temp;
}
}
int main(){
scanf(
"%d%d%d",&n,&
m,&K);
len=
sqrt(n);
for(register
int i=
1;i<=n;i++) scanf(
"%d",&b[i]);
for(register
int i=
1;i<=
m;i++){
scanf(
"%d%d",&
q[i].l,&
q[i].r);
q[i].id=i;
q[i].loc=(
q[i].l-
1)/len+
1;
}
solve();
for(register
int i=
1;i<=
m;i++)
printf(
"%lld\n",final[i]);
return 0;
}