本题要求对于给定的无序数组,求出经过最少多少次相邻元素的交换之后,可以使数组从小到大有序。
思路:典型的求各个数的逆序数题,但是若是直接暴力计算,那么时间复杂度为o(n^2),肯定超时,所以用树状数组来维护,将时间复杂度压缩为o(nlogn)。简单题,可能太久没练树状数组了,打代码的时候树状数组的sum函数忘return 了,导致调了好久
#include<cstdio>
#include<iostream>
#include<cstring>
#include<set>
#include<algorithm>
using namespace std;
struct node
{
int val,id1,id2;
} s[500009];
int N,c[500009];
int lowbit(int x)
{
return x&(x^(x-1));
}
int sum(int end)//计算 c数组中1~end的和 ,所以c应该从1开始计数,而不是0!!!
{
int sum=0;
while(end>0)
{
sum+=c[end];
end-=lowbit(end);
}
return sum;
}
void update(int pos,int num)//N为所有元素的个数,给pos位置上加num
{
while(pos<=N)
{
c[pos]+=num;
pos+=lowbit(pos);
}
}
bool cmp1(node a,node b)
{
return a.val<b.val;
}
bool cmp2(node a,node b)
{
return a.id1>b.id1;
}
int main()
{
//FILE *fp=fopen("t.txt","r");
while(scanf("%d",&N))
{
if(N==0) break;
memset(c,0,sizeof(c));
for(int i=1;i<=N;i++)
{
scanf("%d",&s[i].val);
s[i].id1=i;
}
sort(s+1,s+1+N,cmp1);
for(int i=1;i<=N;i++)
{
s[i].id2=i;
}
sort(s+1,s+1+N,cmp2);
long long ans=0;
for(int i=1;i<=N;i++)
{
update(s[i].id2,1);
ans+=(sum(s[i].id2));
ans--;
}
printf("%lld\n",ans);
}
return 0;
}