總時間限制: 10000ms 單個測試點時間限制: 1000ms本題的典型解法是採用歸併排序。相似題目為「求逆序對數」。記憶體限制: 65536kb
描述
給定n個數的序列a1,a2,...an,定義乙個數對(ai, aj)為「重要逆序對」的充要條件為 i < j 且 ai > 2aj。求給定序列中「重要逆序對」的個數。
輸入
第一行為序列中數字的個數n(1 ≤ n ≤ 200000)。
第二行為序列a1, a2 ... an(0 ≤a ≤ 10000000),由空格分開。
輸出
輸出乙個整數,為給序列中「重要逆序對」的個數。
樣例輸入
10樣例輸出0 9 8 7 6 5 4 3 2 1
16提示如果使用printf輸出long long型別,請用%lld
資料範圍
對於40%的資料,有n ≤ 1000。
在"求逆序對數"中,歸併排序的核心**如下
void merge(int *s, int *temp, int startindex, int endindex, int mid)
else
k ++;
}while(i <= mid)
while(j <= endindex)
for(int i = startindex; i <= endindex; i ++)
}
但是本題所求為「重要逆序對數」,因此我在上機時的做法如下:
void merge(int *s, int *temp, int startindex, int endindex, int mid)
} }
j ++;
}else
k ++;
}while(i <= mid)
while(j <= endindex)
for(int i = startindex; i <= endindex; i ++)
}
但是很不幸的是,tle了。回來後,室友提醒,在裡面加了一重迴圈後,時間複雜度就不是o(nlogn)了,在最壞情況下,應該是o(n^2 logn)。上機時信心滿滿地以為加了break應該不會tle,但是...
室友的做法是建立乙個虛擬指標pointer,從startindex開始,一直指到mid結束。時間複雜度並不會增加。
譬如歸併(0, 6, 7, 8, 9)和(1, 2, 3, 4, 5)時,s[i]指向左邊部分,s[j]指向右邊部分。當pointer指向6,s[j] = 1 時,2 * 1<6;因此6右邊的7,8,9都是重要逆序;pointer指向6,s[j] = 2時,2 * 2 < 6;因此,6右邊的7,8,9都是重要逆序;pointer指向6,s[j] = 3時,2 * 3 = 6,因此需要加pointer右移一位,此時pointer指向的是7,2 * 3 < 7,因此 7右邊的8,9都是重要逆序......以此類推,對於每乙個s[j],都將pointer移動至s[pointer] > 2 * s[j]的位置i處。
顯然pointer最多隻需要移動 n / 2次(從startindex到mid處),因此不會增加複雜度。
完整**如下:
#include using namespace std;
long long sum = 0;
void merge(int *s, int *temp, int startindex, int endindex, int mid)
if(pointer != mid + 1)
j ++;
}else
k ++;
}while(i <= mid)
while(j <= endindex)
for(int i = startindex; i <= endindex; i ++)
}void mergesort(int *s, int *temp, int startindex, int endindex)
}int s[200005] = {};
int temp[400010] = {};
int main()
mergesort(s, temp, 0, n - 1);
cout << sum << endl;
return 0;
}
如果**有問題,還望指出。 poj 2299 求逆序對
題目大意 求逆序對 解題思路 分治法,類似於歸併排序。a 1.n 將原問題劃分為2個子問題a 1.n 2 a n 2 1.n 並且兩個子陣列已經排好序了,1.n 2的逆序對已經求好,n 2 1.n的逆序對也已經求好了 所以求兩個子問題之間的逆序對,在歸併排序的過程中,當a i a j 時,逆序對的數...
樹狀陣列求逆序對 POJ 2299 3067
前幾天開始看樹狀陣列了,然後開始找題來刷。首先是 poj 2299 ultra quicksort 這題是指給你乙個無序序列,只能交換相鄰的兩數使它有序,要你求出交換的次數。實質上就是求逆序對,網上有很多人說它的原理是氣泡排序,可以用歸併排序來求出,但我一時間想不出它是如何和歸併排序搭上邊的 當初排...
poj 2188 歸併排序求逆序對
題目比較繞,但是大意就是求逆序對 幫牛們解開纏繞在一起的繩子 此題允許o n2 但是nlogn就可以過。主要就是如何得到要排序的序列,main函式裡可以清晰看出來。下面是 include include include define m 1001 using namespace std int n,...