HDU1394 Minimum Inversion Number 線段樹+數學,hdu1394inversion

來源:互聯網
上載者:User

HDU1394 Minimum Inversion Number 線段樹+數學,hdu1394inversion
Problem Description

The inversion number of a given number sequence a1, a2, …, an is the number of pairs (ai, aj) that satisfy i < j and ai > aj.

For a given sequence of numbers a1, a2, …, an, if we move the first m >= 0 numbers to the end of the seqence, we will obtain another sequence. There are totally n such sequences as the following:

a1, a2, …, an-1, an (where m = 0 - the initial seqence)
a2, a3, …, an, a1 (where m = 1)
a3, a4, …, an, a1, a2 (where m = 2)

an, a1, a2, …, an-1 (where m = n-1)

You are asked to write a program to find the minimum inversion number out of the above sequences.

Input

The input consists of a number of test cases. Each case consists of two lines: the first line contains a positive integer n (n <= 5000); the next line contains a permutation of the n integers from 0 to n-1.

Output

For each case, output the minimum inversion number on a single line.

Sample Input

10
1 3 6 9 0 8 5 7 4 2

Sample Output

16

解題思路

這題折騰了一晚上才AC 還是太粗心了。

因為資料小,貌似暴力也是可以過的。用線段樹當然更好。
解題分為兩步
①先不考慮移動,用O(nlogn)把初始的逆序對個數算出來(假設是sum)

②用數學公式用O(1)遞推sum 找到最小情況的sum

先看第一步,用線段樹。每讀入一個數我們只考慮在它之前已經讀入的數。便於統計我們將所有的s[i]++成為1-n的正整數。再看當前讀入的這個數和n之間的這一段距離已經存在了幾個數。他們就是當前這個數的”前瞻逆序對”

第二步。假設當前逆序對是sum個。現在考慮第一個數 假設是k 將它放到隊伍的最後面。我們知道在第2到第n個數中有k-1個是小於k的,n-k個是大於k的。所以這麼一移動,自然逆序對數量就少了k-1個,多了n-k個。這樣不斷迴圈,不斷更新最小值。

代碼
#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int maxn = 5010;int n;int s[maxn];int ans[maxn];int segTree[maxn<<2];void update(int node,int k,int l,int r){    if(l <= k && k <= r) segTree[node] ++;    if(l == r) return;    if(r < k || l > k) return;    update(node<<1,k,l,(l+r)/2);    update((node<<1)+1,k,(l+r)/2+1,r);}int query(int a,int b,int node,int l,int r){    if(l > b || r < a) return 0;    if(a <= l && r <= b) return segTree[node];    return query(a,b,node<<1,l,(l+r)/2)+query(a,b,(node<<1)+1,(l+r)/2+1,r);}int main(){    while(scanf("%d",&n) != EOF) {        memset(s,0,sizeof(s));        memset(ans,0,sizeof(ans));        memset(segTree,0,sizeof(segTree));        for(int i = 1 ; i <= n ; i ++) {            scanf("%d",&s[i]);            s[i] ++;            ans[i] = query(s[i],n,1,1,n);            update(1,s[i],1,n);        }        int sum = 0;        for(int i = 1 ; i <= n ; i ++) sum += ans[i];        int mi = sum;        for(int i = 1 ; i < n ; i ++) {            sum = sum+1+n-2*s[i];            if(sum < mi) mi = sum;        }        printf("%d\n",mi);    }    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.