hdu 1394 線段樹求逆序數

來源:互聯網
上載者:User

/*  
    線段樹求逆序數   求小逆序數   神奇

    題意:給定一個序列,對該序列的n種排列(排列如下)的每種排列(0 ~ n-1)的逆序數求最小值:
       a1, a2, ..., an-1, an  
       a2, a3, ..., an, a1  
       a3, a4, ..., an, a1, a2  
       ...  
       an, a1, a2, ..., an-1

    思路:先求出初始序列的逆序數,可以歸併,這裡用的是線段數求。
          設當前逆序數為sum,則每次把第一個數x移到最後,則新序列的逆序數 = sum - x + (n - 1 - x)

          sum = sum - a[i] + (n - 1 - a[i]);      //太神奇了,這個轉移方程.

          
          前面部分用線段樹求初始逆序簡單說一下,就是先建一棵樹,每個節點[l,r]儲存一個sum值,表示到目前為止[l,r]出現的個數。如當前序列為1,3, 則節點[0,3].sum = 2, [0, 4].sum = 2。然後每次掃到一個新的數x都先詢問舊序列中[x+1, n-1]中出現的個數...

          *** 逐個插入值(即輸入的一個值);  在每插入一個值後就更新包含該區間的所有的數的個數(加一)***

*/


#include <stdio.h>#include <algorithm>using namespace std;#define     debug       printf("!\n")#define     MAXN        5005#define     L(x)        ((x)<<1)#define     R(x)        (((x)<<1)|1)#define     MID(x, y)   (((x)+(y))>>1)int a[MAXN], pos[MAXN], high[MAXN];struct Node {    int l, r, sum;} f[MAXN * 3];int n;void Update(int root){    if(root == 0) return ;    f[root].sum++;    Update(root >> 1);}int Query(int root, int l, int r){    if(l <= f[root].l && f[root].r <= r) {        return f[root].sum;    }    int mid = MID(f[root].l, f[root].r);    if(r <= mid) return Query(L(root), l, r);    else if(mid < l) return Query(R(root), l, r);    else return Query(L(root), l, mid) + Query(R(root), mid+1, r);}void build(int root, int l, int r){    f[root].l = l, f[root].r = r, f[root].sum = 0;    if(l == r) {        pos[l] = root;        return ;    }    int mid = MID(l, r);    build(L(root), l, mid);    build(R(root), mid+1, r);}int main(){    int x;    while(scanf("%d", &n) != EOF) {        build(1, 0, n-1);        for(int i = 0; i < n; i++) {            scanf("%d", &x);            a[i] = x;            high[x] = Query(1, x, n-1);            Update(pos[x]);        }        int sum = 0;        for(int i = 0; i < n; i++) sum += high[i];        int ans = sum;        for(int i = 0; i < n; i++) {            sum = sum - a[i] + (n - 1 - a[i]);      //太神奇了,這個轉移方程.            ans = min(ans, sum);        }        printf("%d\n", ans);    }}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.