NOJ [1060] Countless Core Computers

题目链接:http://acm.nbut.cn/Problem/view.xhtml?id=1060
题目要求是输入n,再输入n组数据(a, b),表示区间(a,b)里自加1,接下来输入m,和m组数据,表示m组查询,对每组查询输出其对应的那个点的值(哈希)。
题目数据为500000,5000000,故暴力的哈希一定会被暴力的超时,因此可以用线段树来解决。。(交给信神)
这里介绍另一种巧妙地方法。
首先是对输入数据进行记录,用一个数组z[]进行记录,其中z[a]++,z[b+1]--;其中z[a]表示记录这组数据的起点z[b+1]表示这组数据结束,如下:
for(i=0;i<N;i++){
            scanf("%d%d",&l,&r);
            z[a]++;
            z[b+1]--;
}


接下来是更新与记录了,这时我们再重开一个数组,a[],对a[]进行清空后进行如下操作:
for(i=0;i<=max;i++){
            x+=z[i];a[i]+=x;
        }
这里的max是什么呢?事实上,在我们输入的时候,我们可以把最大的右边的那个数记录下来,这样的话对于比最大的数还大的那些数,必定是0,因此就没必要循环到他们了。因此输入的时候这样写:
x=max=0;
        for(i=0;i<N;i++){
            scanf("%d%d",&a,&b);
            z[a]++;
            z[b+1]--;
            if(b>max)max=b;
        }

然后接下来就是进行查询了,因为类似于哈希直接查下标,故查询的时间为O(1)。
然后完整代码如下:
#include<stdio.h>
#include<string.h>
#define MAXN 5000000+500
int b[MAXN],a[MAXN];
int main(){
    int N,Q;
    int i,j;
    int x,max;
    int l,r;
    while(~scanf("%d",&N)){
        memset(a,0,sizeof(a));
        memset(b,0,sizeof(b));
        x=max=0;
        for(i=0;i<N;i++){
            scanf("%d%d",&l,&r);
            b[l]++;
            b[r+1]--;
            if(r>max)max=r;
        }
        for(i=0;i<=max;i++){
            x+=b[i];a[i]+=x;
        }
        scanf("%d",&Q);
        for(i=0;i<Q;i++){
            scanf("%d",&x);
            printf("%d\n",a[x]);
        }
    }
    return 0;
}
PS:。。。JJ大神自己想出来的,所以JJ大神才是真真的大神;;

你可能感兴趣的:(NOJ [1060] Countless Core Computers)