逆序对(洛谷P1908题题解,Java语言描述)
生活随笔
收集整理的這篇文章主要介紹了
逆序对(洛谷P1908题题解,Java语言描述)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目要求
題目鏈接
分析
逆序對這個說法我們在線性代數應該就接觸過了吧,這里的逆序對應該與序偶也有關吧,總之簡單點說就是順序反了(相較于我們的比較標準)的一對數據。
<1, 2, 3, 4, 5> 是一組數據,它是全部順序無逆序的。
如果我們給出這樣一組數據:<1, 3, 2, 4, 5> ,它只有 2、3 之間是反的,逆序對的數目是1。
如果我們給出這樣一組數據:<1, 3, 4, 2, 5> ,它有 2、3 和 2、4 之間是反的,逆序對的數目是2。
……
那怎么去找呢?
寫一個O(N2)O(N^2)O(N2)的算法嗎?
題目數據被加強了,所以50W的O(N2)O(N^2)O(N2)……很恐怖
線性的算法有點扯,一般想不到,那就想一個O(NlogN)O(NlogN)O(NlogN)的吧,什么呢?
歸并排序!
在每次合并的時候,要么順序保留要么逆序交換,所以在并+交換的時候做一下統計就能得到答案。
歸并排序的思想是分治法,所以本題的歸類也是分治算法,建議好好體會。
關于歸并排序,薦讀:
- 《一文道破Sort的方方面面》
- 《排序算法大全(Java語言描述)》
- 《深夜再侃侃排序》
值得注意的是:由于數據可能達到50W,所以在Java處理的時候注意一些細節,否則可能 T爆被迫換C++ 或是 聽取WA聲一片:
- 使用 long 做counter的數據類型(C++要用longlong)
- 使用BufferedReader來讀,讀取正行;即使使用Scanner也一定不要nextInt()。不然,盲猜必炸
AC代碼(Java語言描述)
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader;public class Main {private static long result = 0;private static int[] nums, temp;private static void mergeSort(int left, int right) {if (left == right) {return;}int mid = (left+right)/2, i = left, j = mid+1, k = left;mergeSort(left, mid);mergeSort(j, right);while (i <= mid && j <= right) {if (nums[i] <= nums[j]) {temp[k++] = nums[i++];} else {temp[k++] = nums[j++];result += mid-i+1;}}while (i <= mid) {temp[k++] = nums[i++];}while (j <= right) {temp[k++] = nums[j++];}for (int m = left; m <= right; m++) {nums[m] = temp[m];}}public static void main(String[] args) throws IOException {BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));int num = Integer.parseInt(reader.readLine());String[] array = reader.readLine().split("\\s+");reader.close();nums = new int[num];temp = new int[num];for (int i = 0; i < num; i++) {nums[i] = Integer.parseInt(array[i]);}mergeSort(0, num-1);System.out.println(result);}}總結
以上是生活随笔為你收集整理的逆序对(洛谷P1908题题解,Java语言描述)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 全排列问题(洛谷P1706题题解,Jav
- 下一篇: 方程求解(洛谷P1689题题解,Java