P2709 小B的询问 (莫队板子)

题目描述

小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。

 

输出格式:

 

M行,每行一个整数,其中第i行的整数表示第i个询问的答案。

 

输入输出样例

输入样例#1: 复制
6 4 3
1 3 2 1 1 3
1 4
2 6
3 5
5 6
输出样例#1: 复制
6
9
5
2

说明

对于全部的数据,1<=N、M、K<=50000

 

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;

const int N=500005;

int n,m,k;
int a[N],c[N];
int ans,Ans[N];
int belong[N];
struct Querry
{
    int tim,l,r;
    bool operator < (const Querry &a) const
    {
        if(belong[l]==belong[a.l]) return belong[r]<belong[a.r];
        return belong[l]<belong[a.l];
    }
}q[N];

int read()
{
    char c=getchar();int num=0;
    for(;!isdigit(c);c=getchar());
    for(;isdigit(c);c=getchar())
        num=num*10+c-'0';
    return num;
}

void init()
{
    n=read(),m=read(),k=read();
    int size=sqrt(n);
    for(int i=1;i<=n;++i)
        a[i]=read(),
        belong[i]=(i-1)/size+1;
    for(int i=1;i<=m;++i)
        q[i].l=read(),q[i].r=read(),q[i].tim=i;
    sort(q+1,q+m+1);
    
}

/*void update(int now,bool type)
{
    if(type)
    {
        ans-=c[now]*c[now];
        ++c[now];
        ans+=c[now]*c[now];
    }
    else
    {
        ans-=c[now]*c[now]; 
        --c[now];
        ans+=c[now]*c[now];
    }
}*/
void update(int now,bool type)
{
    if(type)
        ans+=c[now]<<1|1,++c[now];        //(a+1)*(a+1)==a*a+2*a+1,比a*a多了2*a+1 
    else
        ans-=(c[now]<<1)-1,--c[now];    //(a-1)*(a-1)==a*a-2*a+1,比a*a少了2*a-1 
}

void work()
{
    for(int i=q[1].l;i<=q[1].r;++i)
        update(a[i],1);
    Ans[q[1].tim]=ans;
    for(int i=2;i<=m;++i)
    {
        if(q[i].l>q[i-1].l)
            for(int j=q[i-1].l;j<q[i].l;++j)
                update(a[j],0);
        if(q[i].l<q[i-1].l)
            for(int j=q[i].l;j<q[i-1].l;++j)
                update(a[j],1);
        if(q[i].r<q[i-1].r)
            for(int j=q[i].r+1;j<=q[i-1].r;++j)
                update(a[j],0);
        if(q[i].r>q[i-1].r)
            for(int j=q[i-1].r+1;j<=q[i].r;++j)
                update(a[j],1);
        Ans[q[i].tim]=ans;    
    }
    for(int i=1;i<=m;++i)
        printf("%d\n",Ans[i]);
}

int main()
{
    init();
    work();
    return 0;
}

 

posted @ 2018-02-10 21:04  whymhe  阅读(126)  评论(0编辑  收藏  举报