0~n-1数字组成的序列,然后进行这样的操作,每次将最前面一个元素放到最后面去会得到一个序列,每得到一个序列都可得出该序列的逆序数(如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序。一个排列中逆序的总数就称为这个排列的逆序数)。要求求出最小的逆序数。
输入包含若干组数据,每组数据包含两行,第一行为整数n,第二行是一个0..n-1的排列。
每组数据输出一行一个整数,表示最小的逆序对数量。
10 1 3 6 9 0 8 5 7 4 2
16
n<=100 000最多不超过10组数据.
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<vector> #include<algorithm> #define maxn 100005 #define maxm 100005 #define lowbit(x) (x&(-x)) #define FOR(i,a,b) for(int i=(a);i<=(b);++i) #define ROF(i,a,b) for(int i=(a);i>=(b);--i) using namespace std; typedef long long ll; int n, a[maxn]; int c[maxm]; int l[maxn], r[maxn]; void add(int p){ while(p<=n) c[p]++, p += lowbit(p); } int query(int p){ int ans = 0; while(p) ans += c[p], p -= lowbit(p); return ans; } int main(){ while(scanf("%d",&n) == 1){ FOR(i, 1, n) scanf("%d",&a[i]), a[i]++; memset(c, 0, sizeof(c)); FOR(i, 1, n) l[i] = query(a[i]-1), add(a[i]); memset(c, 0, sizeof(c)); ROF(i, n, 1) r[i] = query(a[i]-1), add(a[i]); ll ans = 0, tmp; FOR(i, 1, n) ans += r[i]; tmp = ans; FOR(i, 1, n-1){ tmp += n - 1 - 2 * (l[i] + r[i]); ans = min(ans, tmp); } printf("%lld\n", ans); } return 0; }
原文:https://www.cnblogs.com/de-compass/p/11426247.html