lightoj-1088 - Points in Segments(二分法)
1088 - Points in Segments
PDF (English) Statistics Forum
Time Limit: 2 second(s) Memory Limit: 32 MB
Given n points (1 dimensional) and q segments, you have to find the number of points that lie in each of the segments. A point pi will lie in a segment A B if A ≤ pi ≤ B.
For example if the points are 1, 4, 6, 8, 10. And the segment is 0 to 5. Then there are 2 points that lie in the segment.
Input
Input starts with an integer T (≤ 5), denoting the number of test cases.
Each case starts with a line containing two integers n (1 ≤ n ≤ 105) and q (1 ≤ q ≤ 50000). The next line contains n space separated integers denoting the points in ascending order. All the integers are distinct and each of them range in [0, 108].
Each of the next q lines contains two integers Ak Bk (0 ≤ Ak ≤ Bk ≤ 108) denoting a segment.
Output
For each case, print the case number in a single line. Then for each segment, print the number of points that lie in that segment.
Sample Input
Output for Sample Input
1
5 3
1 4 6 8 10
0 5
6 10
7 100000
Case 1:
2
3
2
Note
Dataset is huge, use faster I/O methods.
题目大意:给出一些在数轴上的点, 然后给出一段区间,问这段区间上有几个点。
解题思路:写这题的时候看到题目segment 有点先入为主,以为用线段树写,然后就用了分块的方法写,然后MLT ,GG了
这题就是二分查找出对应两端的下标,相减就可以了。
#include<iostream> #include<cstring> #include<cstdio> #include<cmath> using namespace std; const int N = 100010; int T,n,q,under1,under2; int a[N]; //寻找mid 使得a[mid]<=value<a[mid+1] int binaryS(int value){ int l=1,r=n; while(l<=r){ int mid = (l+r)>>1; if(a[mid]>value) r = mid-1; else if(a[mid+1]>value) return mid; else l = mid+1; } return 0; } int main(){ scanf("%d",&T); for(int t=1;t<=T;t++){ scanf("%d%d",&n,&q); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); } printf("Case %d:\n",t); for(int i=0;i<q;i++){ scanf("%d%d",&under1,&under2); if(under1<a[1]) under1 = 0; else{ //因为寻找的是a[mid]<=value<a[mid],所以当a[mid]==under1时应该-1? int temp = binaryS(under1); if(a[temp]==under1) under1 = temp-1; else under1 = temp; } if(under2>=a[n]) under2 = n; else under2 = binaryS(under2); printf("%d\n",under2-under1); } } return 0; } //分块的求法 //const int ss = sqrt(1e8); //int Size[10010]; //int a[100000010]; // //int main(){ // // int T,n,q,val,size,under1,under2,s1,s2,sum; // // scanf("%d",&T); // memset(Size,0,sizeof(Size)); // memset(a,0,sizeof(a)); // for(int t=1;t<=T;t++){ // scanf("%d%d",&n,&q); // for(int i=0;i<n;i++){ // scanf("%d",&val); // a[val] = 1; // Size[int(val/ss)] += 1; // } // printf("Case %d:\n",t); // for(int i=0;i<q;i++){ // sum = 0; // scanf("%d%d",&under1,&under2); // s1 = under1/ss; // s2 = under2/ss; // for(int j = under1;j<=min(under2,(s1+1)*ss-1);j++) sum+=a[j]; // for(int j = s1+1;j<s2;j++) sum += Size[j]; // // if(s1!=s2){ // for(int j=s2*ss;j<=under2;j++) sum+=a[j]; // } // printf("%d\n",sum); // } // // } // // return 0; //} // //