使用线段树优化使得求初始数列的逆序数的时间复杂度从O(n ^ 2) 降到 O(n log(n))
#include <iostream>
using namespace std;
struct node {
int left;
int right;
int cnt;
};
int data[5005];
node seg_tree[5005 * 3];
void create_tree(int left, int right, int loc) {
seg_tree[loc].left = left;
seg_tree[loc].right = right;
seg_tree[loc].cnt = 0;
if (right == left) {
return;
}
int mid = (left + right) / 2;
create_tree(left, mid, loc << 1);
create_tree(mid + 1, right, (loc << 1) + 1);
}
void update_tree(int value, int loc) {
seg_tree[loc].cnt++;
if (seg_tree[loc].right == seg_tree[loc].left && seg_tree[loc].right == value) {
seg_tree[loc].cnt = 1;
return;
}
int mid = (seg_tree[loc].right + seg_tree[loc].left) / 2;
if (value <= mid) {
update_tree(value, loc << 1);
} else {
update_tree(value, (loc << 1) + 1);
}
}
int query_tree(int left, int right, int loc) {
if (seg_tree[loc].left == left && seg_tree[loc].right == right) {
return seg_tree[loc].cnt;
}
int mid = (seg_tree[loc].right + seg_tree[loc].left) >> 1;
if (right <= mid) {
return query_tree(left, right, loc << 1);
} else if (mid < left) {
return query_tree(left, right, (loc << 1) + 1);
} else {
return query_tree(left, mid, loc << 1) + query_tree(mid + 1, right, (loc << 1) + 1);
}
}
int main()
{
int n;
int i, j;
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
#endif
while (scanf("%d", &n) != EOF) {
for (i = 0; i < n; ++i) {
scanf("%d", &data[i]);
}
create_tree(1, n, 1);
int min = 0;
for (i = 0; i < n; ++i) {
min += query_tree(data[i] + 1, n, 1);
update_tree(data[i], 1);
}
int temp = min;
for (i = 0; i < n - 1; ++i) {
temp = temp - data[i] + (n - data[i] - 1);
if (temp < min) {
min = temp;
}
}
cout << min << endl;
}
return 0;
}