题目链接: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]表示这组数据结束,如下:
然后接下来就是进行查询了,因为类似于哈希直接查下标,故查询的时间为O(1)。
然后完整代码如下:
题目要求是输入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[]进行清空后进行如下操作:
}
这里的max是什么呢?事实上,在我们输入的时候,我们可以把最大的右边的那个数记录下来,这样的话对于比最大的数还大的那些数,必定是0,因此就没必要循环到他们了。因此输入的时候这样写:for(i=0;i<=max;i++){ x+=z[i];a[i]+=x; }
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)。
然后完整代码如下:
PS:。。。JJ大神自己想出来的,所以JJ大神才是真真的大神;;#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; }