现在的位置: 首页 > 综合 > 正文

Codeforces Round #136 (Div. 2) Little Elephant and Array

2017年04月25日 ⁄ 综合 ⁄ 共 1007字 ⁄ 字号 评论关闭

http://blog.csdn.net/acm_ted/article/details/7943188


题意:一个n个数字的数字序列,同时有m次询问,问在a,b之间符合数字x刚好出现x次的数有多少个。

题解:由于符合条件的数总数不超过450个,我们可以从此下手,先统计每个数字出现的次数,剔除不可能符合条件的数字,然后h[i][j]表示第i个数字在0~j出现的次数,询问的时候只要对i个数字将0~a-1和0~b两个区间内第i个数出现的次数相减就得到第i个数字在a~b中出现的次数,统计即可。

代码:

#include<cstdio>
#include<cstring>
#include<map>
#define MAX 100005
using namespace std;
struct node
{
    int x,num;
} temp;
int s[MAX],b[450],h[MAX][450];
map<int,struct node> mat;
int main()
{
    int n,m,k,t;
    for(; ~scanf("%d%d",&n,&t);)
    {
        mat.clear();
        for(int i=1; i<=n; ++i)
        {
            scanf("%d",&s[i]);
            //统计一个数出现的次数
            if(mat.count(s[i])==0)
            {
                temp.x=s[i];
                temp.num=1;
                mat.insert(make_pair(s[i],temp));
            }
            else
                (mat.find(s[i])->second.num)++;
        }
        k=0;
        //查找可能符合条件的数
        for(map<int,struct node>::iterator it=mat.begin(); it!=mat.end(); ++it)
            if(it->second.x<=it->second.num)  b[++k]=it->second.x;
        for (int i=1; i<=k; ++i)
        {
            h[0][i]=0;
            for (int j=1; j<=n; ++j)
                if (s[j]==b[i]) h[j][i]=h[j-1][i]+1;
                else            h[j][i]=h[j-1][i];
        }
        int l,r,ans;
        for(;t--;)
        {
            ans=0;
            scanf("%d%d",&l,&r);
            for (int i=1; i<=k; ++i)
                if (h[r][i]-h[l-1][i]==b[i]) ans++;
            printf("%d\n",ans);
        }
    }
    return 0;
}

抱歉!评论已关闭.