1019 逆序数
在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序。一个排列中逆序的总数就称为这个排列的逆序数。
如2 4 3 1中,2 1,4 3,4 1,3 1是逆序,逆序数是4。给出一个整数序列,求该序列的逆序数。
Input
第1行:N,N为序列的长度(n <= 50000)
第2 - N + 1行:序列中的元素(0 <= A[i] <= 10^9)
Output
输出逆序数
Input示例
4
2
4
3
1
Output示例
4
问题链接:51Nod-1019 逆序数
代码1(线段树):
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
const int maxn=5e4+100;
#define ll long long
int a[maxn];
int x[maxn];
struct Tree
{
int left,right;
int val;
}tree[maxn<<2];
void build(int l,int r,int root)
{
tree[root].left=l;
tree[root].right=r;
tree[root].val=0;
if(l==r)
return ;
int mid=l+r>>1;
build(l,mid,root<<1);
build(mid+1,r,root<<1|1);
}
int query(int l,int r,int root)
{
if(l==tree[root].left&&tree[root].right==r)
{
return tree[root].val;
}
int mid=tree[root].left+tree[root].right>>1;
if(l>mid)
return query(l,r,root<<1|1);
else if(r<=mid)
return query(l,r,root<<1);
else
return query(l,mid,root<<1)+query(mid+1,r,root<<1|1);
}
//包含id的区间都加1
void update(int id,int root)
{
tree[root].val++;
if(tree[root].left==tree[root].right)
{
return ;
}
int mid=tree[root].left+tree[root].right>>1;
if(mid>=id) update(id,root<<1);
else update(id,root<<1|1);
}
int Bin(int key,int n)
{
int l=0;
int r=n-1;
while(l<=r)
{
int mid=l+r>>1;
if(x[mid]>key) r=mid-1;
else if(x[mid]==key) return mid;
else l=mid+1;
}
return -1;
}
int main()
{
int n;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%d",&a[i]);
x[i]=a[i];
}
sort(x,x+n);
int m=1;
for(int i=1;i<n;i++)
{
if(x[i]>x[m-1]) x[m++]=x[i];
}
build(0,m,1);
ll sum=0;
for(int i=0;i<n;i++)
{
int id=Bin(a[i],m);
sum+=query(id+1,m,1);
update(id,1);
}
printf("%lld\n",sum);
return 0;
}
解法2(归并算法):(拷了海岛的代码)
/* 51Nod-1019 逆序数 */
#include <bits/stdc++.h>
using namespace std;
const int N = 50000;
int a[N], temp[N], cnt;
void merge(int low, int middle, int high)
{
int i = low, j=middle+1, k = low;
while(i <= middle && j <= high)
{
if(a[i] < a[j])
temp[k++] = a[i++];
else {
cnt += j - k;
temp[k++] = a[j++];
}
}
while(i <= middle)
temp[k++] = a[i++];
while(j <= high)
temp[k++] = a[j++];
for(i=low; i<=high; i++)
a[i] = temp[i];
}
void mergesort(int low, int high)
{
if(low < high)
{
int middle = (low + high) / 2;
mergesort(low, middle);
mergesort(middle+1, high);
merge(low, middle, high);
}
}
int main()
{
int n;
while(~scanf("%d", &n)) {
for(int i = 0; i < n; i++)
scanf("%d", &a[i]);
cnt = 0;
mergesort(0, n - 1);
printf("%d\n", cnt);
}
return 0;
}