樹狀數組求逆序對


Preface

求逆序對的方法有兩種一個是歸並排序,一個是樹狀數組。在這里只講怎么用樹狀數組求逆序對

什么是逆序對?

逆序對就是序列中\(a_i>a_j\)\(i < j\)的有序對。

我們可以先按照權值從大到小排序,現在要求的就是對於一個點有多少在他前面的點下標小於這個點。

那么這個東西怎么弄呢?我們可以用樹狀數組維護。從頭到尾掃一遍,對於每個點,答案就是在這個點下標之前的下標有幾個已經被訪問過,在將這個點在樹狀數組中+1,表示為被訪問過

 for(int i=1;i<=n;i++)
        ans+=sum(a[i].id),add(a[i].id,1);

但是要注意判重復的元素

code

#include<bits/stdc++.h>
#define int long long
#define rg register
#define file(x) freopen(x".in","r",stdin);freopen(x".out","w",stdout);
using namespace std;
int read(){
    int x=0,f=1;
    char c=getchar();
    while(c<'0'||c>'9') f=(c=='-')?-1:1,c=getchar();
    while(c>='0'&&c<='9') x=x*10+c-48,c=getchar();
    return f*x;
}
struct node {
    int x,id;
}a[500001];
int c[500001<<2],n,ans,bj[500001];
bool cmp(const node & a , const node & b ){
    if(a.x==b.x)
        return a.id>b.id;
    return a.x>b.x;
}
int lowbit(int x){
    return x&(-x);
}
int sum(int x){
    int ans=0;
    while(x>0){
        ans+=c[x];
        x-=lowbit(x);
    }
    return ans;
}
void add(int x,int v){
    while(x<=n){
        c[x]+=v;
        x+=lowbit(x);
    }
}
main(){
    n=read();
    for(int i=1;i<=n;i++)
        a[i].id=i,a[i].x=read();
    sort(a+1,a+1+n,cmp);
    for(int i=1;i<=n;i++)
        ans+=sum(a[i].id),add(a[i].id,1);
    printf("%lld",ans);
    return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM