归并排序
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
public class MergeSort {
public static int MAXN = 100001;
public static int[] arr = new int[MAXN];
public static int[] help = new int[MAXN];
public static int n;
public static void main(String[] args) throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StreamTokenizer in = new StreamTokenizer(br);
PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
in.nextToken();
n = (int)in.nval;
for(int i = 0;i < n ;i++){
in.nextToken();
arr[i] = (int)in.nval;
}
// mergeSort1(0,n-1);
mergeSort2();
for (int i = 0; i < n - 1; i++) {
out.print(arr[i] + " ");
}
out.println(arr[n - 1]);
out.flush();
out.close();
br.close();
}
// // 归并排序递归版
// public static void mergeSort1(int l,int r){
// if(l == r){
// return;
// }
// int m = (l + r)/2;
// mergeSort1(l,m);
// mergeSort2(m+1,r);
// merge(l,m,r);
// }
// 归并排序非递归版
// 时间复杂度O(n * logn)
// 空间复杂度O(n)
public static void mergeSort2(){
//step 步长 步长每次增加一倍,步长<n继续
//左部分 merge 右部分
//l ... m m+1...
for(int l,m,r,step = 1; step < n; step = step*2){
l = 0;
while(l < n){
m = l + step -1;//左部分l...m
if(m+1 >= n){//右部分开头>= n了。右部分没东西可以比较了,break
break;
}
//有右部分
//求右部分的右边界
r = Math.min(l+(step*2)-1,n-1);
merge(l,m,r);
l = r + 1 ;
}
}
}
//l...r
//O(n)
public static void merge(int l,int m,int r){
int a = l;
int b = m + 1;
int i = l;
while(a<=m && b<=r){
help[i++] = arr[a] <= arr[b] ? arr[a++] : arr[b++];
}
// 左侧指针、右侧指针,必有一个越界、另一个不越界
while(a<=m){
help[i++] = arr[a++];
}
while(b<=r){
help[i++] = arr[b++];
}
for(i = l;i<=r ;i++){
arr[i] = help[i];
}
}
}
import java.io.*;
public class Main {
public static int MAXN = 100001;
public static int[] arr = new int[MAXN];
public static int n;
public static int[] help = new int[MAXN];
public static void main(String[] args) throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StreamTokenizer in = new StreamTokenizer(br);
PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
while(in.nextToken() !=StreamTokenizer.TT_EOF){
n = (int)in.nval;
for(int i = 0;i < n;i++){
in.nextToken();
arr[i] = (int) in.nval;
}
out.println(smallSum(0,n-1));
}
out.flush();
out.close();
}
public static long smallSum(int l,int r){
//计算数组小数和==》 左部分数组小数和 +右部分数组小数和 + 左跨右的小数和
if(l == r){
return 0;
}
int m = l + (r-l)/2;//取(l,r)中点
return smallSum(l,m) + smallSum(m+1,r) +merge(l,m,r);
}
public static long merge(int l ,int m,int r){
//
long ans = 0;
for(int i = l,j = m + 1,sum = 0;j <= r;j++){
while(i <= m && arr[i]<=arr[j]){
sum += arr[i++];
}
ans += sum;
}
//正常merge
int a = l;
int b = m + 1;
int i = l;
while(a<=m && b<= r){
help[i++] = arr[a] <= arr[b] ? arr[a++] : arr[b++];
}
while(a<=m){
help[i++] = arr[a++];
}
while(b<=r){
help[i++] = arr[b++];
}
for (i = l; i <= r; i++) {
arr[i] = help[i];// 重要:排序好的部分拷贝回 arr
}
return ans;
}
}
class Solution {
//给定数组的长度不会超过50000。
// public static int MAXN = 50001;
//定义数组
//定义归并排序所需要的辅助数组
// public static int[] help = new int[MAXN];
public int reversePairs(int[] nums) {
int[] help = new int[nums.length];
return counts(nums,0,nums.length -1,help);
}
public static int counts(int[] nums,int l, int r,int[] help){
if(l == r){
return 0;
}
//分成求左部分 + 右部分 + 左跨右
//求中点m
int m = l + (r-l)/2 ;
return counts(nums,l,m,help) + counts(nums,m + 1,r,help) + merge(nums,l,m,r,help);
}
public static int merge(int[] nums,int l,int m,int r,int[] help){
//统计部分
int ans = 0;
for(int i = l, j = m + 1;i <= m; i++){
while(j <= r && (long) nums[i] > (long) nums[j]*2){
j++;
}
ans += j - (m + 1);
}
//排序,加速统计
//正常merge 归并排序
int i = l;//定义i用来做辅助数组的指针
int a = l;
int b = m + 1;
while(a <= m && b <= r){
help[i++] = (nums[a] <= nums[b]) ? nums[a++] : nums[b++];
}
while(a <= m){
help[i++] = nums[a++];
}
while(b <= r){
help[i++] = nums[b++];
}
//把排好序的help数组复制到nums数组上去
for(i = l;i <=r; i++){
nums[i] = help[i];
}
return ans;
}
}