求逆序对有三种以上方法:1、离散树状数组,2、线段树,3、归并排序
今天做了下洛谷的P1908逆序对;
1、一开始用树状数组,一直RE,后来在发现自己一直忽略离散化。
#include <iostream> #include <algorithm> using namespace std; const int maxn = 400000+5; typedef long long ll; ll n,Hash[maxn],bt[maxn]; struct node { int v,id; }a[maxn]; ll lowbit(ll x) { return (x)&(-x); } void add(ll i,ll b) { while(i<=n) { bt[i]+=b; i+=lowbit(i); } } ll qu(ll i) { ll ans=0; while(i>0) { ans+=bt[i]; i-=lowbit(i); } return ans; } bool cmp(node a,node b) { return a.v<b.v; } int main(){ cin>>n; for(int i=1; i<=n; i++) { cin>>a[i].v; a[i].id=i; } sort(a+1,a+1+n,cmp); for(int i=1;i<=n;i++) { Hash[a[i].id]=i; } //离散化结束; ll sum = 0; for(int i=1;i<=n;i++) { sum+=(i-1-qu(Hash[i])); //当前树状数组中有i-1个,quary(a[i])前缀和查出a[i]前的个数 add(Hash[i],1); //值为a[i]的数又增加了一个 } cout<<sum<<endl; return 0; }