CodeForces - 220B Little Elephant and Array (莫队+离散化 / 离线树状数组)当成模板题

版权声明:抱最大的希望,为最大的努力,做最坏的打算。 https://blog.csdn.net/qq_37748451/article/details/88251823

题意:N个数,M个查询,求[Li,Ri]区间内出现次数等于其数值大小的数的个数。

分析:用莫队处理离线问题是一种解决方案。但ai的范围可达到1e9,所以需要离散化预处理。每次区间向外扩的更新的过程中,检查该位置的数ai的出现次数是否已经达到ai或ai+1,以判断是否要更新结果。同理,区间收缩的时候判断ai出现次数是否达到ai或ai-1。

这个题用离线树状数组也可以实现

代码:
 

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstdlib>
#include<iomanip>
#include<numeric>
#include<cctype>
#include<cstring>
#include<cmath>
#include<ctime>
#include<queue>
#include<stack>
#include<list>
#include<set>
#include<map>
#define ll long long
#define MAXN 100010
#define MAXM 50010
using namespace std;
const int maxn=1e5+5;
int N,M,res;
struct Node
{
    int val;
    int id;
    bool operator < (const Node &p) const {return val<p.val;}
}a[maxn];
bool cmpid(const Node &x,const Node &y) {return x.id<y.id;}

int b[maxn];
int pos[maxn],cnt[maxn],block;                  //块数
int ans[maxn];
int v[maxn];            //离散化
struct Query{
    int L,R,id;
}Q[maxn];
bool cmp1(const Query& x,const Query& y){       //根据所属块的大小排序
    if(pos[x.L]==pos[y.L]) return x.R<y.R;
    return pos[x.L]<pos[y.L];
}

void add(int pos)
{
    int id = v[a[pos].id];
    if(cnt[id]==b[pos]-1) res++;
    else if(cnt[id]==b[pos]) res--;
    cnt[id]++;
}

void pop(int pos)
{
    int id = v[a[pos].id];
    if(cnt[id]==b[pos]) res--;
    else if(cnt[id]==b[pos]+1) res++;
    cnt[id]--;
}

int main()
{

    int T;
    int cas=1;
    while(scanf("%d%d",&N,&M)==2){
        block = ceil(sqrt(1.0*N));
        memset(cnt,0,sizeof(cnt));
        for(int i=1;i<=N;++i){
            scanf("%d",&a[i].val);
            a[i].id = i;
            b[i] = a[i].val;
            pos[i]=i/block;
        }
        //离散化
        sort(a+1,a+N+1);
        int tag = 1;
        v[a[1].id] = tag;
        for(int i=2;i<=N;++i)
        {
            if(a[i].val == a[i-1].val) v[a[i].id] = tag;
            else v[a[i].id] = ++tag;
        }
        sort(a+1,a+N+1,cmpid);

        for(int i=1;i<=M;++i)
        {
            scanf("%d%d",&Q[i].L,&Q[i].R);
            Q[i].id = i;
        }
        sort(Q+1,Q+M+1,cmp1);
        res=0;
        int curL=1,curR=0;
        for(int i=1;i<=M;++i)
        {
            while(curL>Q[i].L) add(--curL);
            while(curR<Q[i].R) add(++curR);
            while(curL<Q[i].L) pop(curL++);
            while(curR>Q[i].R) pop(curR--);
            ans[Q[i].id] = res;
        }
        for(int i=1;i<=M;++i)
            printf("%d\n",ans[i]);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_37748451/article/details/88251823