線段樹求逆序數方法 HDU1394&&POJ2299

來源:互聯網
上載者:User

標籤:style   blog   color   os   io   for   2014   html   

為什麼線段樹可以求逆序數?


給一個簡單的序列 9 5 3 他的逆序數是3
首先要求一個逆序數有兩種方式:可以從頭開始往後找比當前元素小的值,也可以從後往前找比當前元素大的值,有幾個逆序數就是幾。
線段樹就是應用從後往前找較大值得個數。(一邊更新一邊查)
當前個數是 n = 10
元素   9  5   3

9先加入線段樹,T【9】+=1;查從T【9】到T【10】比9大的值,沒有sum = 0;
5 加入線段樹,T【5】 += 1,查從T【5】到T【10】比5大的值,有一個9,sum +=1;
3 加入線段樹,T【3】 += 1,查從T【3】到T【10】比3大的值,有兩個9和5,sum +=2;
最終sum = 3;


若元素值不能確定,那麼首先講數列離散化,在從前往後枚舉,找後面比前面小的統計個數……
離散化:例如2 5 8 3 10 等價於 1 3 4 2 5,可以通過排序加小小處理解決。
例如:
元素    9 5  3 4 1     離散化後得到索引
索引    1 2 3 4 5
將元素升序排序
元素    1 3 4 5 9
索引    5 3 4 2 1


    枚舉到第i個數,我們需要求出從1到i-1中有多少個比a[i]大的數,更新答案。
    具體怎麼做呢?
    每次枚舉完一個數之後,將這個數插入到線段樹裡(注意:插到與其對應的位置)。
    舉個例子:3 2 4 1。則線段樹的變化應該為:t[3]+=1;t[2]+=1;t[4]+=1;t[1]+=1;
    
  設x=a[i],這樣,在插入一個數X時,首先求一下t[x+1]~t[n]的和,這個和就是1~i-1中有多少個比a[i]大的數
 因為求一個數列的逆序數可以從兩個

在你插a[i]時,前面已經有多少個比a[i]大的數

POJ 2299#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <algorithm>#include <cmath>using namespace std;#define MAX INT_MAX#define MIN INT_MIN#define LL __int64#define init(a) memset(a,0,sizeof(a))#define lson l , m , rt << 1#define rson m + 1 , r , rt << 1 | 1const int maxn = 500010;using namespace std;int T[maxn<<2], index[maxn], num[maxn];int n;int cmp(const int i, const int j){    return num[i] < num[j];}void update( int l, int r,int rt, int num, int add){    T[rt] += add;    if(r==l) return ;    int m = (l+r) >> 1;    if(num <= m) update(lson, num, add);    else update(rson, num, add);}int query( int l, int r, int rt,int L, int R){    if(L<=l && r<=R) return T[rt];    int m = (l+r) >> 1;    int ans = 0;    if(L <= m) ans += query(lson, L, R);    if(R > m) ans += query(rson, L, R);    return ans;}int main(){    while(~scanf("%d", &n))    {        if(n==0) break;        init(index);        for(int i=1;i<=n;i++)        {            scanf("%d", &num[i]);            update(1, n,1, i, 1);//離散化            index[i] = i;        }        sort(index+1, index+n+1,cmp); //排序num,更新索引         LL sum = 0;        for(int i=1;i<=n;i++)        {            sum += (query( 1, n,1, 1, index[i])-1);            update(1, n,1,  index[i], -1);        }        printf("%I64d\n", sum);    }    return 0;}

HDU 1394 
題意:一組數 每次把最前面的元素放在最後產生新的序列,再統計逆序數,求所有逆序中最小值
有一個公式:先求出原數列的逆序數,sum
那麼每次新逆序數 = sum-a[i] + (n-a[i] - 1)

#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <algorithm>#include <cmath>using namespace std;#define MAX INT_MAX#define MIN INT_MIN#define LL __int64#define init(a) memset(a,0,sizeof(a))#define lson l , m , rt << 1#define rson m + 1 , r , rt << 1 | 1const int maxn = 500010;using namespace std;int T[maxn<<2], index[maxn], num[maxn];int n;int cmp(const int i, const int j){    return num[i] < num[j];}void update( int l, int r,int rt, int num, int add){    T[rt] += add;    if(r==l) return ;    int m = (l+r) >> 1;    if(num <= m) update(lson, num, add);    else update(rson, num, add);}int query( int l, int r, int rt,int L, int R){    if(L<=l && r<=R) return T[rt];    int m = (l+r) >> 1;    int ans = 0;    if(L <= m) ans += query(lson, L, R);    if(R > m) ans += query(rson, L, R);    return ans;}int main(){    while(~scanf("%d", &n))    {        if(n==0) break;        init(index);        for(int i=1;i<=n;i++)        {            scanf("%d", &num[i]);            update(1, n,1,  i, 1);            index[i] = i;        }       sort(index+1, index+n+1,cmp);        LL sum = 0;        for(int i=1;i<=n;i++)        {            sum += (query( 1, n,1, 1, index[i])-1);           update(1, n,1,  index[i], -1);        }      //  printf("%I64d\n", sum);        LL  ans = sum;        for(int i = 1;i<=n;i++)        {            sum =  sum - num[i] + (n-num[i]- 1);            ans = min(sum,ans);        }        cout<<ans<<endl;    }    return 0;}


聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.