逆序數 線段樹

2021-09-17 04:21:27 字數 1375 閱讀 7340

既然是區間操作 我們想到了線段樹

我們先建立乙個空樹 然後呢 按照這個序列的順序將每個值插入 ,每次插入伴隨一次查詢 查詢前面插入的比這次插入的大的數字的個數

然後就可以了 複雜度 nlogn 可以接受

題意:就是給出一串數,當依次在將第乙個數變為最後乙個數的過程中,要你求它的最小逆序數。

思路:可以用樹狀陣列和線段數做。這裡我是用線段樹做的。建的是一棵空樹,然後每插入乙個點之前,統計大於這個數的有多少個,直到所有的數都插入完成,就結果了逆序樹的統計。

要得出答案主要是利用了乙個結論,如果是0到n的排列,那麼如果把第乙個數放到最後,對於這個數列,逆序數是減少a[i],而增加n-1-a[i]的.當然,你也可以是統計小於這個數的有多少個,然後再用已經插入樹中i個元素減去小於這個數的個數,得出的結果也是在一樣的。

#include #include #include #include #include #include #include #include #define inf 0x3f3f3f3f

#define lson l,m,rt<<1

#define rson m+1,r,rt<<1|1

const long long mod = 1e9 + 7;

const int maxn = 55555;

using namespace std;

typedef long long ll;

int sum[maxn<<2];

void pushup(int rt)

void build(int l,int r,int rt)

int m=(l+r)>>1;

build(lson);

build(rson);

// pushup(rt);

}void update(int p,int l,int r,int rt)

int m=(l+r)>>1;

if(p<=m)update(p,lson);

else update(p,rson);

pushup(rt);

}int query(int l,int r,int l,int r,int rt)

int m=(l+r)>>1;

int ret=0;

if(l<=m)ret+=query(l,r,lson);

if(r>m)ret+=query(l,r,rson);

return ret;

}int x[maxn];

int main()

int ret = sum;

for (int i = 1 ; i <= n ; i ++)

printf("%d\n",ret);

}return 0;

}

線段樹 求逆序數

hdu1394 minimum inversion number 題意 求inversion後的最小逆序數 思路 用o nlogn 複雜度求出最初逆序數後,就可以用o 1 的複雜度分別遞推出其他解 線段樹功能 update 單點增減 query 區間求和 逆序數 對於 n個不同 的元素,先規定各元素...

逆序數和線段樹的關係

考慮一下逆序數的定義 分別是 2,1 4,3 4,1 3,1 也就是說針對乙個數。判斷在這個序列中這個數字置後面的數有多少個比它小。也就是說針對乙個數。判斷在這個序列中這個數字置之前有多少個數比它大。那就是詢問當前數 n 區間上的出現了多少個數。由於我們詢問順序是從前到後 左到右 所以在當前數前面且...

線段樹或樹狀陣列求逆序數

線段樹或樹狀陣列求逆序數 求逆序數的方法有分治,歸併,本文只介紹線段樹或樹狀陣列求逆序數的辦法,眾所周知,線段樹和樹狀樹可以用來解決區間操作問題,就是因為這兩個演算法區間操作的時間複雜度很低o logn 才讓這種方法具有可行性。首先先來看乙個序列 6 1 2 7 3 4 8 5,此序列的逆序數為5 ...