cf220b

不知道为什么线段树区间更新专题里有这题。。

可以用莫队解,也可以直接开数组解

/*
n个询问,m个元素
O(m*m):记录每个元素出现次数,筛掉出现次数小于数值的数
*/
#include<iostream>
#include<cstring>
#include<cstdio>
#define maxn 100005
using namespace std;
int a[maxn],tot[maxn],s[maxn];//只要统计十万以内的情况
struct Query{
    int l,r,ans;
}q[maxn];//询问
int main(){
    int n,m;
    while(scanf("%d%d",&m,&n)==2){
        memset(q,0,sizeof q);
        memset(s,0,sizeof s);
        memset(a,0,sizeof a);
        memset(tot,0,sizeof tot);

        for(int i=1;i<=m;i++){ 
            scanf("%d",&a[i]);
            if(a[i]<=m)
                tot[a[i]]++;
        }

        for(int i=1;i<=n;i++)
            scanf("%d%d",&q[i].l,&q[i].r);
        
        for(int i=1;i<=m;i++)//统计值小于m的数的出现次数即可,i是当前值
            if(i<=tot[i]){//i不大于其出现次数才能对答案有贡献
                for(int j=1;j<=m;j++)
                    s[j]=s[j-1]+(a[j]==i);//a[j]等于i
                for(int j=1;j<=n;j++)
                    if(s[q[j].r]-s[q[j].l-1] == i) q[j].ans++;//区间[l,r]之间的i出现次数等于i    
            }
        for(int i=1;i<=n;i++)
            printf("%d\n",q[i].ans);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/zsben991126/p/9917659.html