洛谷 P2709 小B的询问 (莫队算法)

传送门

我的第一道莫队题。

以后新学一个算法做的第一题尽量都写一个博客。

其实非常简单,没有什么好讲的。

反正莫队的核心就是分块排序,然后移动选定区间指针,添加或删除元素嘛。

当然因为这是一道莫队门槛题,所以比较简单。

#include <iostream>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#define MAXN 50010
using namespace std;
typedef long long LL;
int n,m,k,pos[MAXN],a[MAXN],cnt[MAXN];
LL sum,ans[MAXN];
struct Ques{
    int l,r,id;
    LL ans;
}q[MAXN];

bool cmp1(Ques x,Ques y){return pos[x.l]<pos[y.l]||pos[x.l]==pos[y.l]&&x.r<y.r;}

int read(){
    int x=0,f=1;char c=getchar();
    while(c<'0'||c>'9') {if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();}
    return x*f;
}

void add(int x){
    if(x<1||x>k) return;
    sum+=2*cnt[x]+1;
    cnt[x]++; 
}

void del(int x){
    if(x<1||x>k) return;
    sum-=2*cnt[x]-1;
    cnt[x]--;
}

int main(){
    n=read();m=read();k=read();
    int sz=sqrt(n);
    for(int i=1;i<=n;i++) a[i]=read(),pos[i]=i/sz;
    for(int i=1;i<=m;i++) {q[i].l=read();q[i].r=read();q[i].id=i;}
    sort(q+1,q+m+1,cmp1);
    int L=0,R=0;
    for(int i=1;i<=m;i++){
        while(R<q[i].r) add(a[R+1]),R++;
        while(R>q[i].r) del(a[R]),R--;
        while(L<q[i].l) del(a[L]),L++;
        while(L>q[i].l) add(a[L-1]),L--;
        ans[q[i].id]=sum;
    }
    for(int i=1;i<=m;i++) printf("%lld\n",ans[i]);
    return 0;
} 

 

posted @ 2019-10-24 19:54  BakaCirno  阅读(134)  评论(0编辑  收藏  举报