逆序对(归并+树状数组)
- 裸题:https://www.luogu.com.cn/problem/P1908
- 逆序对的个数等于在朴素稳定排序情况下,相邻数交换的次数。
使用归并排序求解
对于ans += mid-ii+1 的理解:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int maxn = 5e5+50;
int a[maxn],tmp[maxn];
ll ans=0;
void merge(int l,int mid,int r)
{
int cn = l;
int ii = l,jj = mid+1;
while( ii<=mid && jj<=r )
{
if(a[ii]>a[jj]) //这里可以不一样
{
tmp[cn++] = a[jj++];
ans += mid-ii+1;
}
else
{
tmp[cn++] = a[ii++];
}
}
while(ii<=mid) tmp[cn++] = a[ii++];
while(jj<=r) tmp[cn++] = a[jj++];
for(int i=l;i<=r;i++) a[i] = tmp[i];
}
void msort(int l,int r)
{
if(l<r)
{
int mid = (l+r)/2;
msort(l,mid);
msort(mid+1,r);
merge(l,mid,r);
}
}
int main()
{
int n;scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",a+i);
msort(1,n);
//for(int i=1;i<=n;i++) cout<<bok[i]<<" ";
printf("%lld",ans);
return 0;
}
// 0 1 2 0 3 5
使用离散化+树状数组求解
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int maxn = 5e5+50;
struct node{
int val,id;
}a[maxn];
int num[maxn]; // 相对大小数组(离散化后)
int c[maxn];
int n;
void add(int p,int x)
{
while(p<=n) c[p]+=x,p+=(p&-p);
}
int ask(int p)
{
int res = 0;
while(p) res+=c[p],p-=(p&-p);
return res;
}
int cmp(node a,node b)
{
if(a.val==b.val)
return a.id<b.id;
else
return a.val<b.val;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i].val),a[i].id=i;
sort(a+1,a+n+1,cmp);
for(int i=1;i<=n;i++) num[a[i].id] = i;
ll ans = 0;
for(int i=1;i<=n;i++)
{
add(num[i],1);
ans += i-ask(num[i]);
}
cout<<ans;
return 0;
}
// 0 1 2 0 3 5