B. Little Elephant and Array(莫队)

题目链接:B. Little Elephant and Array

在这里插入图片描述
input

7 2
3 1 2 2 3 3 7
1 7
3 4

output

3
1

题意:

给你一个长度为n的数组,然后m次询问,
每次询问L,R,范围内的总共有多少个出现次数和他数值本身相等的数。

思路:
确实是莫队的板子题,(莫队这个坑,去年到今年一直没填,正好具体的学一下思想和一些小方法)
有一篇大佬的博客讲的不错:莫队算法详解
莫队,优雅的暴力,分块改变了查询的顺序,划定了每一块要查询的范围,就只是这样顺序搞了一下,竟然可以让我们本来 o ( n 2 ) o(n^2) 的复杂度降到了 o ( n n ) o(n√n) 。前面的范围控制在同一块的范围内,然后同一块中的后边界从小到大,在正确的情况下也降低了不少时间复杂度。
这样可以过掉很多题。莫队是一种强制离线的操作。
理解了莫队它优化时间的思想,这道题就很好的可以去练练手,就开个数组记录这个数的出现的次数就行了,一道很好的板题。
AC

#include<bits/stdc++.h>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
#define LL long long
const int N=1e5+10;
struct zxc
{
    LL l,r,id;
}md[N];
LL num[N];
LL L=1,R=0;
LL n,m;
LL fk;
LL a[N];
bool cmp(zxc q,zxc w)
{
    if((q.l/fk)==(w.l/fk))
    {
        return q.r<w.r;
    }
    else
    {
        return q.l<w.l;
    }
}
LL ans[N];
int main()
{
    scanf("%lld%lld",&n,&m);
    for(LL i=1;i<=n;i++)
    {
        scanf("%lld",&a[i]);
    }
    for(LL i=1;i<=m;i++)
    {
        scanf("%lld%lld",&md[i].l,&md[i].r);
        md[i].id=i;
    }
     fk=sqrt(n);
    sort(md+1,md+1+m,cmp);
    LL ax=0;
    for(LL i=1;i<=m;i++)
    {
        while(L<md[i].l)
        {

            if(a[L]<=100000)
            {
                 num[a[L]]--;
                 if(num[a[L]]==a[L])
                 {
                     ax++;
                 }
                 if(num[a[L]]==a[L]-1)
                 {
                     ax--;
                 }
            }
            L++;

        }
        while(L>md[i].l)
        {
            L--;
            if(a[L]<=100000)
            {
                num[a[L]]++;
                 if(num[a[L]]==a[L])
                 {
                     ax++;
                 }
                 if(num[a[L]]==a[L]+1)
                 {
                     ax--;
                 }
            }

        }
        while(R<md[i].r)
        {
            R++;
            if(a[R]<=100000)
            {
                num[a[R]]++;
                if(num[a[R]]==a[R])
                 {
                     ax++;
                 }
                 if(num[a[R]]==a[R]+1)
                 {
                     ax--;
                 }
            }

        }
        while(R>md[i].r)
        {
            if(a[R]<=100000)
            {
                num[a[R]]--;
                if(num[a[R]]==a[R])
                 {
                     ax++;
                 }
                 if(num[a[R]]==a[R]-1)
                 {
                     ax--;
                 }
            }
            R--;
        }
        ans[md[i].id]=ax;
    }
    for(LL i=1;i<=m;i++)
    {
        printf("%lld\n",ans[i]);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_43402296/article/details/105576227