• Codeforces Round #136 (Div. 1) B. Little Elephant and Array


    time limit per test
    4 seconds
    memory limit per test
    256 megabytes
    input
    standard input
    output
    standard output

    The Little Elephant loves playing with arrays. He has array a, consisting of n positive integers, indexed from 1 to n. Let's denote the number with index i as ai.

    Additionally the Little Elephant has m queries to the array, each query is characterised by a pair of integers lj and rj (1 ≤ lj ≤ rj ≤ n). For each query lj, rj the Little Elephant has to count, how many numbers x exist, such that number x occurs exactly x times among numbersalj, alj + 1, ..., arj.

    Help the Little Elephant to count the answers to all queries.

    Input

    The first line contains two space-separated integers n and m (1 ≤ n, m ≤ 105) — the size of array a and the number of queries to it. The next line contains n space-separated positive integers a1a2...an (1 ≤ ai ≤ 109). Next m lines contain descriptions of queries, one per line. The j-th of these lines contains the description of the j-th query as two space-separated integers lj and rj (1 ≤ lj ≤ rj ≤ n).

    Output

    In m lines print m integers — the answers to the queries. The j-th line should contain the answer to the j-th query.

    Sample test(s)
    input
    7 2
    3 1 2 2 3 3 7
    1 7
    3 4
    
    output
    3
    

    1

    这题可以用离线处理,先读入所有的数据,然后保存所有的终点,并按从小到大排序。我采用的是区间更新,单点查询的方法,对于每一个价值value,记录它的个数cnt[value]以及出现的每一个位置pos[value],考虑到开数组可能要很大的内存(10^5)*(10^5),所以用vector<int>pos[maxn]来表示,因为实际上数据输入的内存要远远小于(10^5)*(10^5)。

    从小遍历这n个数,更新cnt[]和pos[],如果出现cnt[value]==value,说明以当前点为终点,起点在1~pos[value][0]都符合,所以这段区间的点都要加1,并开一个结构体pre,记录这一段区间;如果出现cnt[value]>value的时候,说明前一段记录的区间上的点已经不能成立cnt[value]==value,所以该区间都减1,然后新的区间pos[value][pre[value].id-1]+1~pos[value][pre[value].id]都加1,最后查询点就行了。

    代码一:

    #include<iostream>
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<math.h>
    #include<vector>
    #include<map>
    #include<set>
    #include<queue>
    #include<stack>
    #include<string>
    #include<algorithm>
    using namespace std;
    #define maxn 100060
    vector<int>pos[maxn];
    int c[maxn],a[maxn],zd[maxn],cnt[maxn],res[maxn];
    struct edge{
    	int l,r,id;
    }pre[maxn];
    
    struct edge1{
    	int st,ed,id;
    }q[maxn];
    
    struct node{
    	int l,r,num,cnt;
    }b[4*maxn];
    
    bool cmp(edge1 a,edge1 b){
    	return a.ed<b.ed;
    }
    
    bool cmp1(edge1 a,edge1 b){
    	return a.id<b.id;
    }
    
    void build(int l,int r,int i)
    {
    	int mid;
    	b[i].l=l;b[i].r=r;b[i].cnt=0;
    	if(l==r){
    		b[i].num=0;return;
    	}
    	mid=(l+r)/2;
    	build(l,mid,i*2);
    	build(mid+1,r,i*2+1);
    }
    
    void update(int l,int r,int num,int i)
    {
    	int mid;
    	if(b[i].l==l && b[i].r==r){
    		b[i].cnt+=num;return;
    	}
    	if(b[i].cnt){
    		b[i*2].cnt+=b[i].cnt;
    		b[i*2+1].cnt+=b[i].cnt;
    		b[i].cnt=0;
    	}
    	mid=(b[i].l+b[i].r)/2;
    	if(r<=mid)update(l,r,num,i*2);
    	else if(l>mid)update(l,r,num,i*2+1);
    	else{
    		update(l,mid,num,i*2);
    		update(mid+1,r,num,i*2+1);
    	}
    }
    
    int question(int id,int i)
    {
    	int mid;
    	if(b[i].l==id && b[i].r==id){
    		b[i].num+=b[i].cnt;
    		b[i].cnt=0;
    		return b[i].num;
    	}
    	if(b[i].cnt){
    		b[i*2].cnt+=b[i].cnt;
    		b[i*2+1].cnt+=b[i].cnt;
    		b[i].cnt=0;
    	}
    	mid=(b[i].l+b[i].r)/2;
    	if(id<=mid)return question(id,i*2);
    	else return question(id,i*2+1);
    }
    
    int main()
    {
    	int n,m,i,j,t,l,r,ind,value;
    	while(scanf("%d%d",&n,&m)!=EOF)
    	{
    		for(i=1;i<=n;i++){
    			scanf("%d",&a[i]);
    		}
    		for(i=1;i<=m;i++){
    			scanf("%d%d",&q[i].st,&q[i].ed);
    			q[i].id=i;
    		}
    		sort(q+1,q+1+m,cmp);
    		memset(cnt,0,sizeof(cnt));
    		for(i=1;i<=n;i++){
    			pos[i].clear();
    		}
    		
    		build(1,n,1);
    		ind=1;
    		for(i=1;i<=n;i++){
    			value=a[i];
    			if(value<=n){
    				cnt[value]++;
    				pos[value].push_back(i);
    				if(cnt[value]==value){
    					pre[value].l=1;pre[value].r=pos[value][0];pre[value].id=0;
    					update(pre[value].l,pre[value].r,1,1);
    				}
    				else if(cnt[value]>value){
    					update(pre[value].l,pre[value].r,-1,1);
    					pre[value].id++;
    					pre[value].l=pos[value][pre[value].id-1]+1;
    					pre[value].r=pos[value][pre[value].id];
    					update(pre[value].l,pre[value].r,1,1);
    				}
    				while(q[ind].ed==i && ind<=m){
    					res[q[ind].id]=question(q[ind].st,1);
    					ind++;
    				}
    			}
    		}
    		sort(q+1,q+1+m,cmp1);
    		for(i=1;i<=m;i++){
    			if(i==m)printf("%d
    ",res[i]);
    			else printf("%d ",res[i]);
    		}
    	}
    	return 0;
    }

    代码二:
    #include<iostream>
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<math.h>
    #include<vector>
    #include<map>
    #include<set>
    #include<queue>
    #include<stack>
    #include<string>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    #define inf 0x7fffffff
    #define maxn 100060
    #define pi acos(-1.0)
    int num[maxn],pre[maxn],a[maxn];
    int cnt;
    struct node{
        int x,y,idx;
    }ques[maxn];
    
    int ans[maxn];
    struct node1{
        int l,r,num;
    }b[4*maxn];
    
    
    vector<int>pos[maxn];
    vector<int>::iterator p;
    
    bool cmp(node a,node b){
        return a.y<b.y;
    }
    
    void build(int l,int r,int i)
    {
        int mid;
        b[i].l=l;b[i].r=r;b[i].num=0;
        if(l==r)return;
        mid=(l+r)/2;
        build(l,mid,i*2);
        build(mid+1,r,i*2+1);
    }
    
    
    
    void update(int l,int r,int num,int i)
    {
        int mid;
        if(b[i].l==l && b[i].r==r){
            b[i].num+=num;
            return;
        }
        mid=(b[i].l+b[i].r)/2;
        if(r<=mid)update(l,r,num,i*2);
        else if(l>mid)update(l,r,num,i*2+1);
        else{
            update(l,mid,num,i*2);
            update(mid+1,r,num,i*2+1);
        }
    }
    
    void question(int idx,int i)
    {
        int mid;
        if(b[i].l==idx && b[i].r==idx){
            cnt+=b[i].num;
            return;
        }
        cnt+=b[i].num;
        mid=(b[i].l+b[i].r)/2;
        if(idx<=mid)question(idx,i*2);
        else question(idx,i*2+1);
    }
    
    
    
    
    int main()
    {
        int n,m,i,j;
        while(scanf("%d%d",&n,&m)!=EOF)
        {
            for(i=1;i<=n;i++){
                scanf("%d",&a[i]);
            }
            for(i=1;i<=m;i++){
                scanf("%d%d",&ques[i].x,&ques[i].y);
                ques[i].idx=i;
            }
            build(1,100000,1);
            sort(ques+1,ques+1+m,cmp);
            memset(ans,0,sizeof(ans));
            memset(num,0,sizeof(num));
            for(i=1;i<=100000;i++){
                pre[i]=1;
                pos[i].clear();
            }
    
            int wei=1;
            int pre1=1,pre2;
            int flag=1;
            for(i=1;i<=n;i++){
                //printf("---->%d
    ",i);
                if(a[i]<=100000){
                    if(a[i]==1){
                        if(flag){
                            flag=0;
                            update(1,i,1,1);
                            pre2=i;
                        }
                        else{
                            update(pre1,pre2,-1,1);
                            pre1=pre2+1;
                            pre2=i;
                            update(pre1,pre2,1,1);
                        }
                    }
                    else{
                        num[a[i] ]++;
                        if(num[a[i] ]==a[i] ){
                            p=pos[a[i] ].begin();
                            update(pre[a[i] ],*p,1,1);
                            pos[a[i] ].push_back(i);
    
                        }
                        else if(num[a[i] ]==a[i]+1){
                            p=pos[a[i] ].begin();
                            update(pre[a[i] ],*p,-1,1);
                            pre[a[i] ]=*p+1;
                            update(pre[a[i] ],i,1,1);
                            pos[a[i] ].erase(p);
                            pos[a[i] ].push_back(i);
                            num[a[i] ]--;
                        }
                        else{
                            pos[a[i] ].push_back(i);
                        }
                    }
                }
                while(ques[wei].y==i && wei<=m){
                    int l=ques[wei].x;
                    cnt=0;
                    question(l,1);
                    ans[ques[wei].idx ]=cnt;
                    wei++;
                }
            }
            cnt=0;
            question(1,1);
            for(i=1;i<=m;i++){
                printf("%d
    ",ans[i]);
            }
        }
        return 0;
    }
    


  • 相关阅读:
    用Iterator实现遍历集合
    SimpleDateFormat使用详解 <转>
    Java学习之Iterator(迭代器)的一般用法 (转)
    Java:String和Date、Timestamp之间的转换
    关于PreparedStatement.addBatch()方法 (转)
    JavaBean入门及简单的例子
    Tomcat7.0无法启动解决方法[failed to start]
    executeQuery、executeUpdate 和 execute
    jquery中attr和prop的区别
    Jquery的parent和parents(找到某一特定的祖先元素)
  • 原文地址:https://www.cnblogs.com/herumw/p/9464705.html
Copyright © 2020-2023  润新知