CodeForces220B

题意

给出一个长度为(n)的数组,(m)次询问。每一次询问给出两个数(l)(r),表示在区间([l,r])内,查询在给定区间内有多少个数字,该数字出现次

数等于它本身。

思路

题目中的ai最大(10^9),而数组范围(10^5),所以如果数据大于(10^5)了,这个数就不可能为所求的(x)忽略这个数后就不用进行离散化了。

数据过大,我们无法开这么大的数组,所以要对其进行离散化处理,所以可以想到用莫队算法来解决。

AC代码

#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<cmath>
#include<iostream>
using namespace std;
#define inf 0x3f3f3f3f
const int N=1e5+20;
typedef long long ll;

int n,q,sum,a[N],belong[N],ans[N],cnt[N];

inline char gc() //用fread读入加快读入速度,比一般read读入要快
{
    static char buf [100000],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}

inline int  read()
{
    static char c=gc();
    ll x=0,f=1;
    for(; c>'9'||c<'0'; c=gc()) if(c=='-') f=-1;
    for(; c<='9'&&c>='0'; c=gc()) x=(x<<3)+(x<<1)+c-'0';
    return x*f;
}

struct node
{
    int l,r,id;
//    bool operator < (const node &x) const
//    {
//        if(belong[l]==belong[x.l])
//            return r<x.r;
//        else
//            return belong[l]<belong[x.l];
//    }
} x[N];

bool cmp1(node a,node b)
{
    if(belong[a.l]==belong[b.l])
        return a.r<b.r;
    else
       // return a.l<b.l;
        return belong[a.l]<belong[b.l];
}
void print(int x)
{
    if(x<0)
    {
        putchar('-');//putchar比普通输出快
        x=-x;
    }
    if(x>=10)
        print(x/10);
    putchar(x%10+'0');
    printf("
");
}

void add(int x)
{
    if(a[x]>n)
        return;
    if(cnt[a[x]]==a[x])
        sum--;
    cnt[a[x]]++;
    if(cnt[a[x]]==a[x])
        sum++;
}

void del(int x)
{
    if(a[x]>n)
        return;
    if(cnt[a[x]]==a[x])
        sum--;
    cnt[a[x]]--;
    if(cnt[a[x]]==a[x])
        sum++;
}

int main()
{
    // n=read();
    //q=read();
    scanf("%d %d",&n,&q);
    int block=sqrt(n);
    for(int i=1; i<=n; i++)
    {
        scanf("%d",&a[i]);
        //a[i]=read();
        belong[i]=i/block;
    }
    for(int i=1; i<=q; i++)
    {
        scanf("%d %d",&x[i].l,&x[i].r);
        // x[i].l=read();
        //x[i].r=read();
        x[i].id=i;//记录编号
    }
    sort(x+1,x+q+1,cmp1);
    memset(cnt,0,sizeof(cnt));
    int L=1,R=0;
    for(int i=1; i<=q; i++)
    {
        while(x[i].l>L)
            del(L++);
        while(L>x[i].l)
            add(--L);
        while(R<x[i].r)
            add(++R);
        while(R>x[i].r)
            del(R--);
        ans[x[i].id]=sum;
    }
    for(int i=1; i<=q; i++)
        //  print(ans[i]);
        printf("%d
",ans[i]);
    return 0;
}
原文地址:https://www.cnblogs.com/OFSHK/p/13714249.html