TopK
# 前K小 int quicksort(vector<int>& arr,int left,int right) { int tmp = arr[left]; while(left < right) { while(left < right && arr[right] > tmp) right--; arr[left] = arr[right]; while(left < right && arr[left] <= tmp) left++; arr[right] = arr[left]; } arr[left] = tmp; return left; } void TopK(vector<int>& arr,int l,int r,int k) { int index = quicksort(arr,l,r); int num = index-l+1; if(num == k) return; if(num < k ) TopK(arr,index+1,r,k-num); else TopK(arr,l,index-1,k); } #前k大 int partition(int A[], int left, int right) { int temp = A[left]; while(left<right) { while(left<right && A[right]>temp) right--; A[left] = A[right]; while(left<right && A[left]<=temp) left++; A[right] = A[left]; } A[left] = temp; return left; } int Topk_Max(int A[], int left, int right, int k) { if(left==right) return A[left]; int p = partition(A, left, right); if(k==p-left+1) return A[p]; if(k<p-left+1) return KstMax(A, left, p-1, k); else return KstMax(A, p+1, right, k); }
逆序对个数
#include <bits/stdc++.h> using namespace std; //在某个时候,左区间: 5 6 7 下标为i // 右区间: 1 2 9 下标为j // //这个时候我们进行合并: //step 1:由于 5>1,所以产生了逆序对,这里,我们发现,左区间所有还没有被合并的数都比 1 大,所以1与左区间所有元素共产生了 3 个逆序对(即tot_numleft-i+1对),统计答案并合并 1 //step 2:由于 5>2,由上产生了3对逆序对,统计答案并合并 2 //step 3:由于 5<9, 没有逆序对产生,右区间下标 j++ //step 4:由于 6<9, 没有逆序对产生,右区间下标 j++ //step 5:由于 7<9, 没有逆序对产生,右区间下标 j++ //step 6:由于右区间已经结束,正常执行合并左区间剩余,结束 const int maxn = 5e5+10; int a[maxn], temp[maxn]; long long res = 0; void mergeSort(int l, int r) { if(l==r) return; int mid = (l+r)/2, i=l, j=mid+1, index=l; mergeSort(l, mid); mergeSort(mid+1, r); while(i<=mid && j<=r) { if(a[i]<=a[j]) temp[index++]=a[i++]; else { temp[index++] = a[j++]; res += mid-i+1; } } while(i<=mid) temp[index++] = a[i++]; while(j<=r) temp[index++] = a[j++]; for (int i = l; i <= r; ++i) { a[i] = temp[i]; } } int main(int argc, char const *argv[]) { int n; scanf("%d", &n); for (int i = 0; i < n; ++i) { scanf("%d", &a[i]); } mergeSort(0, n-1); printf("%lld ", res); return 0; }