法一:归并排序
#include <stdio.h>
#include <string.h>
#define N 100
int a[N], b[N], n;
int Calc(int first, int last)
{
if (first == last-1) return 0;
int mid = (first+last)/2, i = first, j = mid, k = first,
res = Calc(first, mid)+Calc(mid, last);
while (i < mid && j < last)
{
if (a <= a[j]) b[k++] = a[i++], res += j-mid;
else b[k++] = a[j++];
}
while (i < mid) b[k++] = a[i++], res += j-mid;
while (j < last) b[k++] = a[j++];
memcpy(a+first, b+first, sizeof(b[0])*(last-first));
return res;
}
int main()
{
int res = 0;
scanf("%d", &n);
for (int i = 0; i < n; ++i)
scanf("%d", &a);
printf("%d\n", Calc(0, n));
return 0;
}
或
#include <stdio.h>
#define max 1000001
long long a[max],b[max];
long long count;
void Merge(long long a[], int start, int mid , int end) //归并排序的合并部分
{
int i = start,j = mid + 1,k = start;
while(i <= mid&&j <= end)
{
if(a[i] <= a[j])
{
b[k++] = a[i++];
}
else
{
count += j - k;//统计逆序数对
b[k++] = a[j++];
}
}
while(i <= mid)
{
b[k++] = a[i++];
}
while(j <= end)
{
b[k++] = a[j++];
}
for(int i = start; i <= end; i++)
{
a[i] = b[i];
}
}
void MergeSort(long long a[], int start, int end) //归并排序
{
if(start < end)
{
int mid = (start + end)/2;
MergeSort(a,start,mid); // 将前半部分排序
MergeSort(a,mid+1,end); // 将后半部分排序
Merge(a,start,mid,end); // 合并前后两个部分
}
}
int main(int argc, char const *argv[])
{
int n,m;
scanf("%d",&n);
while(n--)
{
scanf("%d",&m);
count = 0;
for(int i = 0; i < m; i++)
{
scanf("%d",a+i);
}
MergeSort(a,0,m-1);
printf("%lld\n",count);
}
return 0;
}
法二:树状数组
#include <stdio.h>
#define N 100
int a[N+1];
void Inc(int x)
{
for (; x <= N; x += (x^x-1)&x)
++a[x];
}
int Sum(int x)
{
int res = 0;
for (; x; x -= (x^x-1)&x)
res += a[x];
return res;
}
int main()
{
int n, res = 0;
for (scanf("%d", &n); n; --n)
{
int t;
scanf("%d", &t);
res += Sum(N-t);
Inc(N-t+1);
}
printf("%d\n", res);
return 0;
}
或
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#include <string.h>
using namespace std;
const int maxn=500005;
int n;
int aa[maxn]; //离散化后的数组
int c[maxn]; //树状数组
struct Node{
int v;
int order;
}in[maxn];
int lowbit(int x)
{
return x&(-x);
}
void update(int t,int value)
{
int i;
for(i=t;i<=n;i+=lowbit(i))
{
c[i]+=value;
}
}
int getsum(int x)
{
int i;
int temp=0;
for(i=x;i>=1;i-=lowbit(i))
{
temp+=c[i];
}
return temp;
}
bool cmp(Node a ,Node b)
{
return a.v<b.v;
}
int main()
{
int i,j;
while(scanf("%d",&n)==1 && n)
{
//离散化
for(i=1;i<=n;i++)
{
scanf("%d",&in[i].v);
in[i].order=i;
}
sort(in+1,in+n+1,cmp);
for(i=1;i<=n;i++) aa[in[i].order]=i;
//树状数组求逆序
memset(c,0,sizeof(c));
long long ans=0;
for(i=1;i<=n;i++)
{
update(aa[i],1);
ans+=i-getsum(aa[i]);
}
cout<<ans<<endl;
}
return 0;
}
法三:线段树
#include <stdio.h>
#define N 100
int a[N*2-1];
void Inc(int root, int first, int last, int x)
{
++a[root];
if (first == last-1) return;
if (x < (first+last+1)/2) Inc(root*2+1, first, (first+last+1)/2, x);
else Inc(root*2+2, (first+last+1)/2, last, x);
}
int Sum(int root, int first, int last, int x)
{
if (first == last-1) return a[root];
return (x < (first+last+1)/2 ? Sum(root*2+1, first, (first+last+1)/2, x) : 0)
+ Sum(root*2+2, (first+last+1)/2, last, x);
}
int main()
{
int n, res = 0;
for (scanf("%d", &n); n; --n)
{
int t;
scanf("%d", &t);
res += Sum(0, 1, N+1, t+1);
Inc(0, 1, N+1, t);
}
printf("%d\n", res);
return 0;
}