P2709 小B的询问

思路

简单的莫队,开个桶记录下颜色出现次数即可

代码

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
int sum,color[200200],L,R,n,m,a[200200],belong[200200],sz,ans[200200],b[200200],tx;
struct Query{
    int l,r,id;
    bool operator < (const Query &b) const{
        return belong[l]==belong[b.l]?r<b.r:belong[l]<belong[b.l];
    }
}Q[200200];
void init(void){
    int sz=sqrt(n);
    for(int i=1;i<=n;i++)
        belong[i]=(i-1)/sz+1;
}
void moveL(int opt){
    if(opt==1){
        sum-=color[a[L]]*color[a[L]];
        color[a[L]]--;
        sum+=color[a[L]]*color[a[L]];
        L++;
    }
    else{
        L--;
        sum-=color[a[L]]*color[a[L]];
        color[a[L]]++;
        sum+=color[a[L]]*color[a[L]];
    }
    // printf("L=%d sum=%d\n",L,sum);
}
void moveR(int opt){
    if(opt==1){
        R++;
        sum-=color[a[R]]*color[a[R]];
        color[a[R]]++;
        sum+=color[a[R]]*color[a[R]];
    }
    else{
        sum-=color[a[R]]*color[a[R]];
        color[a[R]]--;
        sum+=color[a[R]]*color[a[R]];
        R--;
    }
    // printf("R=%d sum=%d\n",R,sum);
}
int main(){
    int k;
    scanf("%d %d %d",&n,&m,&k);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]),b[i]=a[i];
    sort(b+1,b+n+1);
    tx=unique(b+1,b+n+1)-(b+1);
    for(int i=1;i<=n;i++)
        a[i]=lower_bound(b+1,b+tx+1,a[i])-b;
    // for(int i=1;i<=n;i++)
    //     printf("%d ",a[i]);
    for(int i=1;i<=m;i++){
        scanf("%d %d",&Q[i].l,&Q[i].r);
        Q[i].id=i;
    }
    init();
    sort(Q+1,Q+m+1);
    L=1;
    R=sum=0;
    for(int i=1;i<=m;i++){
        while(L>Q[i].l)
            moveL(-1);
        while(R<Q[i].r)
            moveR(1);
        while(L<Q[i].l)
            moveL(1);
        while(R>Q[i].r)
            moveR(-1);
        ans[Q[i].id]=sum;
    }
    for(int i=1;i<=m;i++){
        printf("%d\n",ans[i]);
    }
    return 0;
}

posted @ 2019-05-08 16:19  dreagonm  阅读(80)  评论(0编辑  收藏  举报