归并排序求逆序对
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<vector>
#include<stack>
#include<queue>
#include<map>
#define RG register
#define IL inline
#define pi acos(-1.0)
#define ll long long
using namespace std;
const int maxn = 500100;
int n;
long long tot;
int a[maxn],tmp[maxn];
void m_sort(int l, int r) {
if(l==r) return;
int mid=(l+r)>>1;
m_sort(l,mid),m_sort(mid+1,r);
int i=l,j=mid+1,p=l;
while(i<=mid && j<=r) {
if(a[i]>a[j]) {
tot=tot+mid-i+1;
tmp[p++]=a[j++];
}
else tmp[p++]=a[i++];
}
while(i<=mid) tmp[p++]=a[i++];
while(j<=r) tmp[p++]=a[j++];
for(int k=l; k<=r; k++) a[k]=tmp[k];
}
int main() {
while(scanf("%d", &n)!=EOF) {
for(int i=1; i<=n; i++)
scanf("%d", &a[i]);
tot=0;
m_sort(1,n);
printf("%lld\n", tot);
}
return 0;
}
/*
1、归并排序:先保证两个子区间是有序的
2、求逆序对:如果a[j]<a[i],说明a[j]比区间[i,k]中的任何一个元素都小而位置又在j之前,所以提供了(k-i+1)对逆序对
*/
树状数组求逆序对
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
typedef long long ll;
#define lowbit(x) (x&-x)
const int MAX = 100010;
int n;
struct node{
ll value;
ll pos;
}q[MAX];
bool cmp(node a,node b){
return a.value < b.value;
}
ll dat[MAX];
ll sum(int i){
ll res = 0;
while(i > 0){
res += dat[i];
i -= lowbit(i);
}
return res;
}
void add(int i){
while(i <= n){
dat[i] += 1;
i += lowbit(i);
}
}
int aa[MAX];
int main(void){
memset(dat,0,sizeof(dat));
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%lld",&q[i].value);
q[i].pos = i;
}
stable_sort(q+1,q+1+n,cmp);//这里不能用sort,因为sort是一个不稳定的排序,在元素相同时也有可能发生交换
for(int i=1;i<=n;i++){
aa[q[i].pos] = i;
}
ll ans = 0;
for(int i=1;i<=n;i++){
ans += (i - sum(aa[i]) - 1);
add(aa[i]);
}
printf("%lld\n",ans);
}