题意:
给一个n个整数组成的序列,每次只能交换相邻的两个元素,问你最少要进行多少次交换才能使得整个整数序列上升有序。
题解:
冒泡排序的交换次数等于数组中所有数的逆序数之和。逆序数可以用树状数组求出。具体操作:
构建范围为1-n的树状数组,每次出现一次,该位置就加1,所以对于每个j,树状数组得到的前n项和就是满足i<j,ai<=aj的i的个数。从而可以用总的可以减去上面的个数,便可以得到前面比ai大的个数。
然后考虑到,数组中元素范围比较大,数组中元素数目比较少。所以要离散化。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn = 500000+1000;
int c[maxn];
int lowbit(int x)
{
return x & -x;
}
int sum(int x)
{
int res=0;
while(x>0)
{
res+=c[x];
x-=lowbit(x);
}
return res;
}
void add(int x,int v)
{
while(x<maxn)
{
c[x]+=v;
x+=lowbit(x);
}
}
struct node
{
int v,index;
bool operator < (const node& a)const
{
return v<a.v;
}
}a[maxn];//原始
int b[maxn];//离散化后
int main()
{
int n;
while(cin>>n,n)
{
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i].v);
a[i].index = i;
}
sort(a+1,a+1+n);
b[a[1].index]=1;
for(int i=2;i<=n;i++)///离散化
{
if(a[i].v == a[i-1].v)
b[a[i].index] = b[a[i-1].index ];
else
b[a[i].index] = i;
}
memset(c,0,sizeof c);
long long ans=0;
for(int i=1;i<=n;i++)
{
ans += i-1-sum(b[i]);///总的减去比它小的
add(b[i],1);
}
cout<<ans<<endl;
}
}