8
11
2015
0

3781: 小B的询问

3781: 小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<=NMK<=50000

 

 

莫队算法

#include<cmath>
#include<cstdio>
#include<algorithm>
using namespace std;
int N,M,K,P;
int A[50010];
int cnt[50010];
struct Mo{
    int k;
    int l,r,BL;
    int ans;
    Mo(){}
    Mo(int x,int a,int b){
        k=x; l=a; r=b; BL=(a-1)/K+1;
    }
}Que[50010];
bool cmp(const Mo &a,const Mo &b){
    return a.BL<b.BL || a.BL==b.BL&&a.r<b.r;
}
bool cmp_k(const Mo &a,const Mo &b){
    return a.k<b.k;
}
int main(){
    scanf("%d%d%d",&N,&M,&P);
    for (int i=1;i<=N;++i)
        scanf("%d",&A[i]);
    K=sqrt(N);
    for (int i=1;i<=M;++i){
        int x,y;
        scanf("%d%d",&x,&y);
        Que[i]=Mo(i,x,y);
    }
    sort(Que+1,Que+M+1,cmp);
    int l=1,r=1,Ans=1;
    cnt[A[1]]=1;
    for (int i=1;i<=M;++i){  
        for (;r<Que[i].r;)
            Ans=Ans+2*(cnt[A[++r]]++)+1;    
        for (;r>Que[i].r;)
            Ans=Ans-2*(cnt[A[r--]]--)+1;    
        for (;l<Que[i].l;)
            Ans=Ans-2*(cnt[A[l++]]--)+1;    
        for (;l>Que[i].l;)
            Ans=Ans+2*(cnt[A[--l]]++)+1;         
        Que[i].ans=Ans;
    }
    sort(Que+1,Que+M+1,cmp_k);
    for (int i=1;i<=M;++i)
        printf("%d\n",Que[i].ans);
}
Category: BZOJ | Tags: bzoj 莫队算法 | Read Count: 292

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter

Host by is-Programmer.com | Power by Chito 1.3.3 beta | Theme: Aeros 2.0 by TheBuckmaker.com