二分法咱们都晓得,二分的根本过程如下(_merge()见下):
//void erfen(int l,int r){//二分递归之后归并 // int mid;// mid = (l + r) / 2;// if(l < r){// erfen(l,mid);// erfen(mid + 1,r);// }// _merge(l,mid,r);//}
Points in Segments(二分分治)
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
1
5 3
1 4 6 8 10
0 5
6 10
7 100000
Case 1:
2
3
2
#include<iostream>#include<algorithm>#include<string>#include<string.h>#include<cstdio>#include<queue>#include<stack> #include<set> #include<vector> using namespace std;/*lower_bound( begin,end,num):从数组的begin地位到end-1地位二分查找第一个大于或等于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,失去找到数字在数组中的下标。upper_bound( begin,end,num):从数组的begin地位到end-1地位二分查找第一个大于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,失去找到数字在数组中的下标。*/int a[100010];int main(){ int t = 0; scanf("%d",&t); for(int i = 1; i <= t; i++){ int n1,n2; scanf("%d %d",&n1,&n2);// int a[100010]; for(int j = 0; j < n1; j++){ scanf("%d",&a[j]); } printf("Case %d:\n",i); while(n2--){ int q1,q2,ans1,ans2; scanf("%d %d",&q1,&q2); ans1 = (int)(upper_bound(a,a + n1,q2) - a);//最大值处用upper_bound必须找到比他大的那个地位 // ans1 = (int)(lower_bound(a,a + n1,q2) - a); ans2 = (int)(lower_bound(a,a + n1,q1) - a);//最小值处用lower_bound就能够,找到等于他的的那个地位就能够 printf("%d\n",ans1 - ans2); } } return 0;}
逆序对个数(归并排序)
给出一个数组a,问这个数组中有多少个逆序对。
逆序对定义:若i<j且a[i]>a[j],则(a[i],a[j])是一个逆序对。
如数组3 4 1 2中的逆序对有(3,1),(3,2),(4,1),(4,2),共4个逆序对。
Input
第一行一个整数n,示意元素个数。
第二行n个空格分隔的整数a[i]。
Output
一个数,示意逆序对个数。
Sample Input 1
5
3 3 4 1 2
Sample Output 1
6
Hint
50%的数据 n ≤ 6000.
————————————————
参考自https://blog.csdn.net/qq_4464...
//#include<iostream>//#include<algorithm>//#include<string>//#include<string.h>//#include<cstdio>//#include<queue>//#include<stack> //#include<set> //#include<vector> //using namespace std;//int a[100010],b[100010];//long long n,ans;//void _merge(int l,int mid,int r){//归并排序代码 // int p1,p2;// p1 = l;// p2 = mid + 1;// for(int i = l; i <= r; i++){// b[i] = a[i];// }// int x;// for( x = p1; p1 <= mid && p2 <= r; x++){// if(b[p1] > b[p2]){// ans += mid - p1 + 1;//计算逆序数对数 // //参考https://blog.csdn.net/qq_44643644/article/details/105880856// a[x] = b[p2++];//// cout << ans << x << endl;// }else{// a[x] = b[p1++];// }// }// while(p1 <= mid){//前半表未取完,持续 // a[x++] = b[p1++];// }// while(p2 <= mid){//后半表未取完,持续// a[x++] = b[p2++];// } //} //void erfen(int l,int r){//二分递归之后归并 // int mid;// mid = (l + r) / 2;// if(l < r){// erfen(l,mid);// erfen(mid + 1,r);// }// _merge(l,mid,r);//}//int main(){// scanf("%lld",&n);// for(int i = 1; i <= n; i++){// scanf("%d",&a[i]);// }// erfen(1,n);// printf("%lld\n",ans);// return 0;//}