HW14-分治
就是课上讲了的比较基础的两道题。
A:输出前k大的数
- 总时间限制:
- 10000ms
- 单个测试点时间限制:
- 1000ms
- 内存限制:
- 65536kB
- 描述
-
给定一个数组,统计前k大的数并且把这k个数从大到小输出。
- 输入
- 第一行包含一个整数n,表示数组的大小。n < 100000。
第二行包含n个整数,表示数组的元素,整数之间以一个空格分开。每个整数的绝对值不超过100000000。
第三行包含一个整数k。k < n。 - 输出
- 从大到小输出前k大的数,每个数一行。
- 样例输入
-
10 4 5 6 9 8 7 1 2 3 0 5
- 样例输出
-
9 8 7 6 5
1 #include<iostream> 2 #include<algorithm> 3 using namespace std; 4 int n, k, a[100005]; 5 void arrangeRight(int l, int r, int m){ //把前m大的数放到最右边 6 if(l >= r) return; 7 int i = l, j = r; 8 int key = a[l]; 9 while(i!=j){ 10 while(j>i && a[j]>=key) j--; 11 swap(a[i], a[j]); 12 while(i<j && a[i]<=key) i++; 13 swap(a[i], a[j]); 14 }//处理完后a[i] = k; 15 int finish = r-i+1; 16 if(finish == m) return; 17 if(finish > m) arrangeRight(i+1, r, m); 18 else if(finish < m) arrangeRight(l, i-1, m-finish); 19 } 20 int main(){ 21 cin>>n; 22 int i; 23 for(i = 0; i < n; i++) 24 cin>>a[i]; 25 cin>>k; //前k大 26 arrangeRight(0, n-1, k); 27 sort(a+n-k, a+n); 28 for(i = n-1; i >= n-k; i--) 29 cout<<a[i]<<endl; 30 return 0; 31 }
备注:嗷,就是只排一半的快排。一个是别忘了l>=r的时候要return,还有注意finish是已经排完的数(在数组右边),个数应当是r-i+1。
B:求排列的逆序数
- 总时间限制:
- 1000ms
- 内存限制:
- 65536kB
- 描述
-
在Internet上的搜索引擎经常需要对信息进行比较,比如可以通过某个人对一些事物的排名来估计他(或她)对各种不同信息的兴趣,从而实现个性化的服务。
对于不同的排名结果可以用逆序来评价它们之间的差异。考虑1,2,…,n的排列i1,i2,…,in,如果其中存在j,k,满足 j < k 且 ij > ik, 那么就称(ij,ik)是这个排列的一个逆序。
一个排列含有逆序的个数称为这个排列的逆序数。例如排列 263451 含有8个逆序(2,1),(6,3),(6,4),(6,5),(6,1),(3,1),(4,1),(5,1),因此该排列的逆序数就是8。显然,由1,2,…,n 构成的所有n!个排列中,最小的逆序数是0,对应的排列就是1,2,…,n;最大的逆序数是n(n-1)/2,对应的排列就是n,(n-1),…,2,1。逆序数越大的排列与原始排列的差异度就越大。
现给定1,2,…,n的一个排列,求它的逆序数。
- 输入
- 第一行是一个整数n,表示该排列有n个数(n <= 100000)。
第二行是n个不同的正整数,之间以空格隔开,表示该排列。 - 输出
- 输出该排列的逆序数。
- 样例输入
-
6 2 6 3 4 5 1
- 样例输出
-
8
- 提示
- 1. 利用二分归并排序算法(分治);
2. 注意结果可能超过int的范围,需要用long long存储。 - 来源
- 习题(15-4)
1 #include<iostream> 2 #include<algorithm> 3 using namespace std; 4 const int N = 100005; 5 int n, a[N], temp[N]; 6 long long ans; 7 void merge(int l, int m, int r){ 8 int i = l, k = l, j = m+1; //l-m一段,m+1到r一段 9 while(i <= m && j <= r){ 10 if(a[i]>a[j]){ 11 temp[k++] = a[j++]; 12 ans += m - i + 1; 13 } 14 else temp[k++] = a[i++]; 15 } 16 while(i<=m)temp[k++] = a[i++]; 17 while(j<=r)temp[k++] = a[j++]; 18 for(i = l; i <= r; i++) 19 a[i] = temp[i]; 20 } 21 void merge_sort(int l, int r){ 22 if(l < r){ 23 int mid = (l+r)/2; 24 merge_sort(l, mid); 25 merge_sort(mid+1,r); 26 merge(l, mid, r); 27 } 28 } 29 30 int main(){ 31 int i; 32 cin>>n; 33 for(i = 0; i < n; i++) 34 cin>>a[i]; 35 merge_sort(0, n-1); 36 cout<<ans<<endl; 37 return 0; 38 }
备注:这个就是以前也写过求逆序对……没啥好说的

浙公网安备 33010602011771号