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 }

备注:这个就是以前也写过求逆序对……没啥好说的

posted @ 2020-05-05 20:33  timeaftertime  阅读(345)  评论(0)    收藏  举报