学习了两种解法。
归并排序
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn = 5e5 + 10;
int a[maxn];
ll ans = 0;
#define in(c) c = read()
#define REP(i,k,n) for(long long i = k; i < n; i++)
inline long long read()
{
long long x=0, f=1;char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-1;
for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
return x * f;
}
void merge2(int q[], int l, int mid, int r){
int lindex = l, rindex = mid + 1,teamindex = 0;
int *team = new int[r-l+1];
while(lindex <= mid && rindex <= r){
if(q[lindex] <= q[rindex])team[teamindex++] = q[lindex++];
else{
team[teamindex++] = q[rindex++];
ans += mid - lindex + 1;//求逆序对数
}
}
while(lindex <= mid){team[teamindex++] = q[lindex++];}
while(rindex <= r){team[teamindex++] = q[rindex++];}
for(int i = 0; i < teamindex; i++)
q[l + i] = team[i];
//delete team;
}
void merge1(int q[], int l, int r){
int mid = (l + r) / 2;
if(l < r){
merge1(q, l, mid);
merge1(q, mid + 1, r);
merge2(q, l, mid, r);
}
}
int main()
{
int n;
in(n);
memset(a, 0, sizeof(a));
REP(i, 0, n)
in(a[i]);
merge1(a, 0, n-1);
printf("%lld\n", ans);
return 0;
}
树状数组
- 树状数组求逆序对
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
typedef long long ll;
int tree[500010], rankk[500010], n;
ll ans;
#define in(c) c = read()
inline long long read()
{
long long x=0, f=1;char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-1;
for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
return x * f;
}
struct point{
int num, val;
}a[500010];
inline bool cmp(point q, point w)
{
if(q.val == w.val)//第二关键字
return q.num < w.num;
return q.val < w.val;
}
inline void insert(int p, int d)
{
for(; p <= n; p+=p &-p)
tree[p]+=d;
}
//p+=p&-p就是p+=lowbit(p),利用了计算机反码的性质,树状数组就是这么来的
inline int query(int p)
{
int sum = 0;
for(; p; p-=p&-p)
sum+=tree[p];
return sum;
}
int main()
{
in(n);
for(int i = 1; i <= n; i++)
{
in(a[i].val );
a[i].num = i;
}
sort(a+1, a+n+1, cmp);
for(int i = 1; i <= n; i++)
rankk[a[i].num ] = i;
for(int i = 1; i <= n; i++)
{
insert(rankk[i], 1);
ans += i - query(rankk[i]);
}
printf("%lld\n", ans);
return 0;
}