1. 程式人生 > >咳咳,用樹狀陣列求逆序對及例題

咳咳,用樹狀陣列求逆序對及例題

關於樹狀陣列,相信大家都已經比較熟悉了。。。
那麼,我們就先來砍一刀例題(嘻嘻)

輸入

給出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; }