首页 > 代码库 > HDU - 1394 Minimum Inversion Number (线段树求逆序数)
HDU - 1394 Minimum Inversion Number (线段树求逆序数)
Description
The inversion number of a given number sequence a1, a2, ..., an is the number of pairs (ai, aj) that satisfy i < j and ai > aj.
For a given sequence of numbers a1, a2, ..., an, if we move the first m >= 0 numbers to the end of the seqence, we will obtain another sequence. There are totally n such sequences as the following:
a1, a2, ..., an-1, an (where m = 0 - the initial seqence)
a2, a3, ..., an, a1 (where m = 1)
a3, a4, ..., an, a1, a2 (where m = 2)
...
an, a1, a2, ..., an-1 (where m = n-1)
You are asked to write a program to find the minimum inversion number out of the above sequences.
For a given sequence of numbers a1, a2, ..., an, if we move the first m >= 0 numbers to the end of the seqence, we will obtain another sequence. There are totally n such sequences as the following:
a1, a2, ..., an-1, an (where m = 0 - the initial seqence)
a2, a3, ..., an, a1 (where m = 1)
a3, a4, ..., an, a1, a2 (where m = 2)
...
an, a1, a2, ..., an-1 (where m = n-1)
You are asked to write a program to find the minimum inversion number out of the above sequences.
Input
The input consists of a number of test cases. Each case consists of two lines: the first line contains a positive integer n (n <= 5000); the next line contains a permutation of the n integers from 0 to n-1.
Output
For each case, output the minimum inversion number on a single line.
Sample Input
10 1 3 6 9 0 8 5 7 4 2
Sample Output
16
题意:每次可以将第一个放到最后一个,求这个过程中最小的逆序数和
思路:线段树的点更新,首先读入序列的时候就可以算出一个逆序数,找找比它大的数的个数,
之后将第一个a[0]放到最后一个的时候,每次减少的是a[0],增加的是(n-a[0]-1)
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #define lson(x) ((x) << 1) #define rson(x) ((x) << 1 | 1) using namespace std; const int MAXN = 5005; const int ROOT = 1; const int inf = 0x3f3f3f3f; // single point updated struct seg{ int w; }; struct segment_tree { seg node[MAXN * 4]; void update(int pos) { node[pos].w = node[lson(pos)].w + node[rson(pos)].w; } void build(int l, int r, int pos) { if (l == r) { node[pos].w = 0; return; } int m = l + r >> 1; build(l, m, lson(pos)); build(m + 1, r, rson(pos)); update(pos); } void modify(int l, int r, int pos, int x, int y) { if (l == r) { node[pos].w = 1; return; } int m = l + r >> 1; if (x <= m) modify(l, m, lson(pos), x, y); else modify(m + 1, r, rson(pos), x, y); update(pos); } int query(int l, int r, int pos, int x, int y) { if (x <= l && r <= y) return node[pos].w; int m = l + r >> 1; int res = 0; if (x <= m) res += query(l, m, lson(pos), x, y); if (y > m) res += query(m + 1, r, rson(pos), x, y); return res; } int remove(int l, int r, int pos, int x) { if (l == r) { node[pos].w = 0; return l; } int m = l + r >> 1; int res; if (x < node[lson(pos)].w) res = remove(l, m, lson(pos), x); else res= remove(m + 1, r, rson(pos), x - node[lson(pos)].w); update(pos); return res; } } tree; int main() { int n; int a[MAXN]; while (scanf("%d", &n) != EOF) { tree.build(1, n, 1); int cnt = 0; for (int i = 0; i < n; i++) { scanf("%d", &a[i]); cnt += tree.query(1, n, 1, a[i]+1, n); tree.modify(1, n, 1, a[i]+1, 1); } int ans = cnt; for (int i = 0; i < n-1; i++) { cnt += (n - 2*a[i] - 1); ans = min(ans, cnt); } printf("%d\n", ans); } return 0; }
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。