21 计算数组的小和
Table of Contents

ac

import java.util.Scanner;


public class Main {

    public static Scanner sc = new Scanner(System.in);

    /**
     * 时间复杂度O(N*logN)
     * 空间复杂度O(N)
     * @param args
     */
    public static void main(String[] args) {

        int n = sc.nextInt();
        int[] arr = new int[n];
        for(int i=0;i<n;i++){
            arr[i] = sc.nextInt();
        }
        long rs = 0;
        if(n > 1){
            rs = getRs(arr, 0 , n-1);
        }
        System.out.println(rs);
    }

    /**
        递归处理
     */
    static long getRs(int[] arr, int left, int right){
        if(left >= right){
            return 0;
        }
        int mid = (right - left) / 2 + left;
        return getRs(arr, left, mid) + getRs(arr, mid+1, right) + mergeGet(arr, left, mid+1, right);
    }


    /*
       [left, mid - 1]
       [mid, right]
     */
    static long mergeGet(int[] arr, int left, int mid, int right){
        if(left >= right){
            return 0;
        }
        int[] tmpArr = new int[right - left + 1];
        int index = 0;
        long smallSum = 0;
        int i = left;
        int j = mid;
        // 左右排过序后 获取小数sum 相对简单
        while (i <= mid-1 && j <= right){
            if(arr[i] <= arr[j]){
                smallSum += arr[i] * (right - j + 1);
                tmpArr[index ++] = arr[i ++];
            }else{
                tmpArr[index ++] = arr[j++];
            }
        }
        // 整体排序后构造新对arr
        if(i <= mid - 1){
            for(int k = i; k <= mid - 1; k ++){
                tmpArr[index ++] = arr[k];
            }
        }
        if(j <= right){
            for(int k = j; k <= right; k ++){
                tmpArr[index ++] = arr[k];
            }
        }
        for(int k=left;k<=right;k++){
            arr[k] = tmpArr[k-left];
        }
        return smallSum;
    }

}
/*
6
1 3 5 2 4 6

27
 */

归并方法类似题:逆序对