
原来求逆序数还可以用线段树,涨姿势了。
首先求出原始序列的逆序数,然后递推每一个序列的逆序数。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; const int maxn = + ; int n, p, qL, qR;
int sum[maxn], a[ + ]; void update(int o, int L, int R)
{
if(L == R) { sum[o]++; return; }
int M = (L + R) / ;
if(p <= M) update(o*, L, M);
else update(o*+, M+, R);
sum[o] = sum[o*] + sum[o*+];
} int query(int o, int L, int R)
{
if(qL <= L && qR >= R) return sum[o];
int ans = ;
int M = (L + R) / ;
if(qL <= M) ans += query(o*, L, M);
if(qR > M) ans += query(o*+, M+, R);
return ans;
} int main()
{
//freopen("in.txt", "r", stdin); while(scanf("%d", &n) == )
{
memset(sum, , sizeof(sum)); for(int i = ; i < n; i++) scanf("%d", &a[i]);
int inv = ;
for(int i = ; i < n; i++)
{
p = a[i];
qL = a[i]; qR = n - ;
inv += query(, , n - );
update(, , n - );
}
int ans = inv;
for(int i = ; i < n; i++)
{
inv = inv + n - a[i]* - ;
ans = min(ans, inv);
}
printf("%d\n", ans);
} return ;
}
线段树
既然要求逆序数了,干脆树状数组,归并排序也都试一试。
由于树状数组lowbit的特点,所以数组下标是从1开始的。但是树状数组要比线段树好写很多。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; const int maxn = + ;
int n;
int a[maxn], s[maxn]; inline int lowbit(int x) { return x&(-x); } int sum(int x)
{
int ans = ;
while(x > ) { ans += s[x]; x -= lowbit(x); }
return ans;
} void add(int x, int d)
{
while(x <= n) { s[x] += d; x += lowbit(x); }
} int main()
{
//freopen("in.txt", "r", stdin); while(scanf("%d", &n) == )
{
memset(s, , sizeof(s));
for(int i = ; i < n; i++) { scanf("%d", &a[i]); a[i]++; }
int inv = ;
for(int i = ; i < n; i++)
{
inv += sum(n) - sum(a[i]);
add(a[i], );
}
int ans = inv;
for(int i = ; i < n; i++)
{
inv = inv + n + - a[i]*;
ans = min(ans, inv);
}
printf("%d\n", ans);
} return ;
}
树状数组
下面是归并排序,_(:зゝ∠)_
代码不长,但是感觉还是挺容易写错的。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; const int maxn = + ;
int n, inv;
int a[maxn], b[maxn], T[maxn]; void MergeSort(int x, int y)
{
if(y - x > )
{
int m = (x + y) / ;
int p = x, q = m, i = x;
MergeSort(x, m); MergeSort(m, y);
while(p < m || q < y)
{
if(q >= y || (p < m && a[p] <= a[q])) T[i++] = a[p++];
else { T[i++] = a[q++]; inv += m - p; }
}
for(i = x; i < y; i++) a[i] = T[i];
}
} int main()
{
//freopen("in.txt", "r", stdin); while(scanf("%d", &n) == )
{
for(int i = ; i < n; i++) { scanf("%d", &a[i]); b[i] = a[i]; }
inv = ;
MergeSort(, n);
int ans = inv;
for(int i = ; i < n; i++)
{
inv = inv + n - - b[i]*;
ans = min(ans, inv);
}
printf("%d\n", ans);
} return ;
}
归并排序