使用线段树优化使得求初始数列的逆序数的时间复杂度从O(n ^ 2) 降到 O(n log(n)) /* Author: ACb0y Date: 2010年11月16日14:59:06 Type: math ProblemId: hdu 1394 Minimum Inversion Number Result: 3201273 2010-11-16 14:55:27 Accepted 1394 62MS 380K 1741 B G++ ACb0y 备注:本题使用了线段树进行优化。速度提高了4倍左右,时间复杂度从n^2 降到nlog(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; }