今天做了下POJ2299,逆序数的2种方法:
1.归并排序法:
2.树状数组:
1.归并排序法:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
long long ans;
int c[500100];
int a[500100];
void merge(int l,int m,int r)
{
int i = l,j = m+1;
int cnt = 0;
while(i<=m && j<=r)
{
if(a[i]<a[j]){c[cnt++] = a[i];i++;}
else
{
ans += m-i+1;
c[cnt++] = a[j];
j++;
}
}
//cout << ans << endl;
while(i<=m){c[cnt++] = a[i];i++;}
while(j<=r){c[cnt++] = a[j];j++;}
//cout << cnt << endl;
for(i=l;i<=r;i++)
a[i] = c[i-l];
}
void mergesort(int l,int r)
{
if(l<r)
{
int m = (r+l)>>1;
mergesort(l,m);
mergesort(m+1,r);
merge(l,m,r);
}
}
int main()
{
//freopen("input.txt","r",stdin);
int n;
while(scanf("%d",&n),n)
{
ans = 0;
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
mergesort(0,n-1);
printf("%I64d\n",ans);
}
return 0;
}
2.树状数组:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define lowbit(x) (x&-x)
struct node
{
int val,no;
};
node a[500100];
int aa[500100];
int c[500100];
int n;
void update(int x,int d)
{
for(int i=x;i<=n;i+=lowbit(i))
c[i]+=d;
}
int getsum(int x)
{
int sum = 0;
for(int i=x;i>0;i-=lowbit(i))
sum += c[i];
return sum;
}
bool cmp(const node& n1,const node& n2)
{
return n1.val < n2.val;
}
int main()
{
while(scanf("%d",&n),n)
{
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i].val);
a[i].no = i;
}
sort(a+1,a+n+1,cmp);
for(int i=1;i<=n;i++)
aa[a[i].no] = i;
memset(c,0,sizeof(c));
long long ans = 0;
for(int i=1;i<=n;i++)
{
update(aa[i],1);
ans += i-getsum(aa[i]);
}
printf("%I64d\n",ans);
}
return 0;
}