【模板】莫队

传送门

题目描述

小B 有一个长为 n 的整数序列 a,值域为 [1,k]。
他一共有 mm 个询问,每个询问给定一个区间 [l,r],求:

其中 ci 表示数字 i 在 [l,r] 中的出现次数。
小B请你帮助他回答询问。

输入格式

第一行三个整数 n,m,k。

第二行 n 个整数,表示 小B 的序列。

接下来的 m 行,每行两个整数 l,r。

输出格式

输出 m 行,每行一个整数,对应一个询问的答案。

 

说明/提示

【数据范围】
对于 100% 的数据,1n,m,k5×10^4。


 

莫队模板↓

#include<iostream>
#include<sstream>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<queue>
#include<algorithm>
using namespace std;
int ans=0,cs[500001],a[500001],Ans[500001],n,Q,k,Size;
struct node{
    int l,r,num;
}q[500001];
int cmp(node XXX,node YYY){
    if(XXX.l/Size==YYY.l/Size) return XXX.r<YYY.r;
    return XXX.l/Size<YYY.l/Size;
}
int del(int X){
    ans-=(2*cs[a[X]]-1);//(X-1)^2=X^2-2*X+1;
    cs[a[X]]--;
    return 0;
}
int add(int X){
    ans+=(2*cs[a[X]]+1);//(X+1)^2=X^2+2*X+1;
    cs[a[X]]++;
    return 0;
}
int main(){
    scanf("%d%d%d",&n,&Q,&k);
    Size=(int)sqrt(n);//离散分块
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    for(int i=1;i<=Q;i++){
        scanf("%d%d",&q[i].l,&q[i].r);
        q[i].num=i;
    }
    sort(q+1,q+Q+1,cmp);
    int l=1,r=0;
    for(int i=1;i<=Q;i++){
        int L=q[i].l,R=q[i].r;
        while(l<L) del(l++);
        while(l>L) add(--l);
        while(r<R) add(++r);
        while(r>R) del(r--);
        Ans[q[i].num]=ans;
    }
    for(int i=1;i<=Q;i++) printf("%d\n",Ans[i]);
    return 0;
}

 

posted @ 2020-08-21 15:21  latent_Lin  阅读(112)  评论(0)    收藏  举报