知识补充:
1、lower_bound(arr,arr+n,stu)//查找第一个大于等于stu的地址
在数组中的下标就是lower_bound(arr,arr+n,stu) - arr;
2、upper_bound(arr,arr+n,stu)//查找第一个大于stu的地址
在数组中的下标就是lower_bound(arr,arr+n,stu) - arr;
一、
归并排序:
#include<iostream>
using namespace std;
int q[100010],tmp[100010];
void merge_sort(int q[],int l,int r) {
if(l>=r) return ;
int mid = (l+r)>>1;
merge_sort(q,l,mid);
merge_sort(q,mid+1,r);
int i = l,j = mid + 1,k = 0;
while(i <= mid && j <= r){ //二路合并
if(q[i]<=q[j]) tmp[k++] = q[i++]; //
else tmp[k++] = q[j++]; //
}
if(i<=mid) for(i;i <= mid;i++) tmp[k++] = q[i];
else for(j ;j <= r;j++) tmp[k ++] = q[j];
for(i = l,k = 0;i <= r;i ++,k++) q[i] = tmp[k];//将临时存入数组还给q[]
}
二路合并:
数组被分为两段 L[ ]和R[ ];长度相等;
二、求逆序数:
数组2 3 1 4的逆序数是2;(2 1)和(3 1);
数组对换成升顺的排列,需要互换的次数==逆序数
求逆序数是在归并排序的基础之上做修改;
#include<iostream>
using namespace std;
int q[100010],tmp[100010];
long long merge_sort(int q[],int l,int r) {
if(l>=r) return 0;
int mid = (l+r)>>1;
int res = merge_sort(q,l,mid)+merge_sort(q,mid+1,r);//res记录各段的逆序数;
int i = l,j = mid + 1,k = 0;
while(i <= mid && j <= r) {
if(q[i]<=q[j]) tmp[k++] = q[i++];
else tmp[k++] = q[j++],res += mid-i+1;//i往后到mid之间的数都比i那个数大
} //i到mid/的数也都比j那个数大,所以逆序数+mid-i+1
if(i<=mid) for(i; i <= mid; i++) tmp[k++] = q[i];
else for(j ; j <= r; j++) tmp[k ++] = q[j];
for(i = l,k = 0; i <= r; i ++,k++) q[i] = tmp[k];
return res;
}