如2 4 3 1中,2 1,4 3,4 1,3 1是逆序,逆序数是4。给出一个整数序列,求该序列的逆序数。
第2 - N + 1行:序列中的元素(0 <= A i <= 10^9)
4 2 4 3 1
4
题意我就不说了,汉语大家都能看懂;
可用插入排序 和 归并排序来解这道题;
二分查找 插入排序 vertor容器
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#include<vector>
vector<int > v;
void init()
{
v.clear();
}
int main()
{
int i,j,n;
while(~scanf("%d",&n))
{
init();
int k;
int sum = 0;
for(i = 0; i < n;i ++)
{
scanf("%d",&k);
sum += v.end() - upper_bound(v.begin(),v.end(),k);
v.insert(upper_bound(v.begin(),v.end(),k),k);
}
printf("%d\n",sum);
}
return 0;
}
这个 vertor 容器是和数组一样,可以用地址减地址,看这个两个数中间有多少个数,但 set ,本身就是 红黑树(平衡树),树形结构,虽说插入就有序,但他不能用地址减地址 算中有多少个元素;这编译器出错;
归并排序:
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define Max 50050
int n,ans;
int a[Max];
int b[Max];
void solve(int a[],int b[],int star,int mid,int end) // 归并排序,把a[shar...mid]和a[mid+1...end],
{ // 两个有序的序列合并成 1 个,合并到b数组对应的位置;
int i = star;
int j = mid + 1;
int k = star;
while(i<=mid&&j<=end)
{
if(a[i]<=a[j])
{
b[k++] = a[i++];
}
else
{
b[k++] = a[j++];
ans += mid - i +1; // a[j] 数前面有几个大于自己的数;
}
}
while(i<=mid)
b[k++] = a[i++];
while(j<=end)
b[k++] = a[j++];
}
void mergersort(int a[],int b[],int star,int end)
{
if(star<end)
{
int mid = (star+end)>>1;
mergersort(b,a,star,mid); // 左数组 左右数组相邻
mergersort(b,a,mid+1,end); // 右数组 为什么每一次调用都把a,b 数组的位置都换位置?
solve(a,b,star,mid,end); // 若是合并a数组中的两个序列时,就是按a数组排,按顺序排好,赋于b数组中
} // 可以认为这是b数组的左数组(子树),b的右数组可以通过右递归完成;这时候b中的两个数组是有序的,所以这时候要按
} //b 数组排,合并的a数组中;就这样,谁是有序的就按谁排,并赋予的另一个数组中;交替有序;所以每次递归a,b数组都要交换位置;
int main()
{
int i,j;
while(~scanf("%d",&n))
{
ans = 0;
for(i=0;i<n;i++)
{
scanf("%d",&a[i]);
b[i] = a[i];
}
mergersort(a,b,0,n-1);
printf("%d\n",ans);
}
return 0;
}