求题中n种序列的最小逆序数。
逆序数的概念是:满足< ai, aj > (i < j 并且 ai > aj) 的组数。
首先求出给定序列的逆序数,可以通过线段树来求。
利用线段树来查询[当前元素+1, n-1]。
然后把当前元素所在的所有区间的结点+1。
最后通过当前序列的逆序数递推其他状态的逆序数即可。
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define lson rt << 1
#define rson rt << 1 | 1
using namespace std;
int maxn[5005 << 2];
void update(int l, int r, int rt, int where)
{
maxn[rt]++;
if(l == r) return;
int mid = (l + r) >> 1;
if(where <= mid) update(l, mid, lson, where);
else update(mid + 1, r, rson, where);
}
int query(int l, int r, int rt, int L, int R)
{
if(L <= l && R >= r) return maxn[rt];
int ans = 0;
int mid = (l + r) >> 1;
if(mid >= L) ans = query(l, mid, lson, L, R);
if(mid < R) ans += query(mid + 1, r, rson, L, R);
return ans;
}
int main()
{
int n, a[10000], ans, minn;
while(~scanf("%d", &n))
{
memset(maxn, 0, sizeof(maxn));
ans = 0;
for(int i = 0; i < n; i++)
{
scanf("%d", &a[i]);
ans += query(0, n-1, 1, a[i], n-1);
update(0, n-1, 1, a[i]);
}
minn = ans;
for(int i = 0; i < n; i++)
{
ans += n - a[i] - a[i] - 1;
minn = min(ans, minn);
}
printf("%d\n", minn);
}
return 0;
}