浏览器标题切换
浏览器标题切换end

CodeForces220B - Little Elephant and Array - 莫队模板

题意

给出一个长度为\(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("\n");
}

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\n",ans[i]);
    return 0;
}
posted @ 2020-09-22 19:13  抓水母的派大星  阅读(98)  评论(0编辑  收藏  举报