怎么求逆序对的数量呢?一种特殊写法告诉你
Posted 行码棋
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了怎么求逆序对的数量呢?一种特殊写法告诉你相关的知识,希望对你有一定的参考价值。
求逆序对的必备知识
我们要求逆序对,就要求前面的数比后面的数大的数对有多少个。
那么如果我们把每个数前面比它大的数有多少个求出来就可以了,答案就显而易见,就是每个数前面比它大的数的个数的和。
那么问题转化为求每个数前面比它大的数的个数。
怎么求呢?
我们考虑到可以用树状数组tr[]维护一个数组
先将原数组进行离散化,因为可能原数组的数据范围很大,数组空间不能开的很大。离散化之后原数组就变成了一个相对大小等级的数。(数小代表这个数值小相对其他数小)
然后每访问一个数,就把树状数组相对应等级的位置加一,代表该等级有一个数存在,然后i-sum(a[i])代表已经访问数的个数减去小于等于a[i]的数的个数(其实就是前面出现的大于a[i]的数的个数)
注意:树状数组存储的是数的大小等级(相对大小)
累加一下就好了
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 5e5+5;
ll a[N],b[N],tr[N];
ll n;
void add(int p,int x)
{
while(p<=n){tr[p]+=x;p+=p&-p;}
}
ll sum(int x)
{
ll res = 0;
while(x){res+=tr[x];x-=x&-x;}
return res;
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++) {cin>>a[i];b[i]=a[i];}
sort(b+1,b+1+n);//必须先排序才能去重
int len = unique(b+1,b+1+n)-b-1;//去重
for(int i=1;i<=n;i++)
a[i] = lower_bound(b+1,b+1+len,a[i])-b;
ll ans = 0;
for(int i=1;i<=n;i++)
{
add(a[i],1);
ans += i-sum(a[i]);
// cout<<i-sum(a[i])<< "\\n";
}
cout<<ans<<'\\n';
return 0;
}
以上是关于怎么求逆序对的数量呢?一种特殊写法告诉你的主要内容,如果未能解决你的问题,请参考以下文章