原题链接:http://poj.org/problem?id=2299
题意:求冒泡排序交换数字的次数
分析:起初听别人说挑战上的冒泡排序交换次数,一直是一头雾水。某天仔细想想,瞬间懂了。
其实就是把给数列按照给你的顺序插入到另一个数组中,插入的位置就是这个数在已经排好序的情况下所在的位置。所以前面的都是比它小,后面的都比它大。
通过很便捷的计算就能算出答案。
for (int j = 0; j < n; j++)[ ans += j - sum(a[j]); add(a[j], 1); ]
sum(a[j])就是<=a[j]的已经插入的数的个数,j-sum(a[j])就是>a[j]的个数。
但是本题999999999过大,需要离散化。
代码:
1 const int maxn = 500010; 2 int bit[maxn]; 3 struct Num { 4 int val; 5 int pos; 6 bool operator <(const Num &a)const { 7 return val < a.val; 8 } 9 }num[maxn]; 10 int n; 11 12 int lowbit(int x) { 13 return x&-x; 14 } 15 16 int sum(int i) { 17 int res = 0; 18 while (i > 0) { 19 res += bit[i]; 20 i -= lowbit(i); 21 } 22 return res; 23 } 24 25 void add(int i, int x) { 26 while (i <= n) { 27 bit[i] += x; 28 i += lowbit(i); 29 } 30 } 31 32 33 34 35 void solve() { 36 while (cin >> n&&n) { 37 memset(bit, 0, sizeof(bit)); 38 ll ans = 0; 39 for (int i = 0; i < n; i++) { 40 cin >> num[i].val; 41 num[i].pos = i; 42 } 43 sort(num, num + n); 44 for (int i = 0; i < n; i++) { 45 int tmp = sum(num[i].pos + 1); 46 cout << tmp << endl << endl; 47 ans += i - tmp; 48 add(num[i].pos + 1, 1); 49 } 50 cout << ans << endl; 51 } 52 }
时间: 2024-10-11 16:47:20