咳咳,用樹狀陣列求逆序對及例題
阿新 • • 發佈:2018-12-16
關於樹狀陣列,相信大家都已經比較熟悉了。。。
那麼,我們就先來砍一刀例題(嘻嘻)
輸入
給出n以及n個數,求這其中的逆序對個數
PS:逆序對,就是序列中ai>aj且i<j的有序對。
輸入:
6
5 4 2 6 3 1
輸出:
11
n<=5*10^5
ai<=10^9
嗯。。。
這一題,很多人應該都會選擇歸併求逆序對吧。。。
但是,樹狀陣列求逆序對我們也應該要掌握掌握的說。
那麼,想讓我們想一想,逆序對應該怎麼快速求呢?
我們可以倒著列舉。
void add(int x) {for (;x<=n;x+=lowbit(x)) t[ x]++;}
int total(int x) {int s=0; for (;x>0;x-=lowbit(x)) s+=t[x]; return s;}
for (int i=n;i>0;i--)
add(c[i]),ans+=total(c[i]-1);
因為ai<=10^9,我們很容易就能想到離散化
這個離散化呢,還要小心一點就是相等的情況。
n=read();//read()為讀入優化
for (int i=1;i<=n;i++) a[i]=(node){read(),i};
sort(a+1,a+n+1,cmp);c[a[1].num]=1;
for (int i= 2;i<=n;i++)
{
if (a[i].val!=a[i-1].val) tot++;
c[a[i].num]=tot;
}
這樣,我們就能簡單而又容易地打出程式碼啦!
#include<cstdio>
#include<algorithm>
#define ll long long
#define lowbit(x) x&-x
#define N 500010
using namespace std;
struct node{ll val,num;}a[N];
ll ans=0,t[N]={0},c[N];int n,tot=1;
inline int read ()
{
int x=0,f=1; char c=getchar();
while(c<'0' || c>'9') f=(c=='-') ? -1:f,c=getchar();
while(c>='0' && c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x*f;
}
int cmp(node x,node y) {return x.val<y.val;}
void add(int x) {for (;x<=n;x+=lowbit(x)) t[x]++;}
ll total(int x) {ll s=0; for (;x>0;x-=lowbit(x)) s+=t[x]; return s;}
int main()
{
// freopen("nxd.in","r",stdin);
// freopen("nxd.out","w",stdout);
n=read();
for (int i=1;i<=n;i++) a[i]=(node){read(),i};
sort(a+1,a+n+1,cmp);c[a[1].num]=1;
for (int i=2;i<=n;i++)
{
if (a[i].val!=a[i-1].val) tot++;
c[a[i].num]=tot;
}
for (int i=n;i>0;i--)
add(c[i]),ans+=total(c[i]-1);
printf("%lld\n",ans);
return 0;
}