NOJ [1060] Countless Core Computers

来源:互联网 发布:java 调用ant 编辑:程序博客网 时间:2024/06/05 22:33
题目链接: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+500int 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大神才是真真的大神;;
0 0