程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> hdu - 1394 - Minimum Inversion Number

hdu - 1394 - Minimum Inversion Number

編輯:C++入門知識

題意:輸入一個整數n(n <= 5000),然後輸入0至n-1的一個序列a[1],a[2],...,a[n],把a[1]放到a[n]後面,又成一個序列,再把a[2]放到a[1]後面,又成一個序列……求這幾個序列的最小逆序對數。   ——>>寒假訓練賽第一場的C題,今天用樹狀數組過了。         只要求出第一個序列的逆序對數就好辦了。這裡,個人用BIT來求。         1 3 6 9   0 8 5 7 4 2 (因為樹狀樹組的結點從1開始,於是加個1,映射一下)         2 4 7 10 1 9 6 8 5 3,這時,從右往左,用cnt計數逆序對數,訪問3,前3項和為0(這裡不是a的前3項和),把3這個位置標記,加到BIT裡去,接著訪問5,前5項和為1,因為剛才3的位置標了一個1,cnt += sum[5]就有了1,把5這個位置標記,加到BIT裡去,接著訪問8,前8項和為2,因為3和5的位置標了一個1……這就求出了逆序對數。 www.2cto.com          接著求其他n-1個序列的逆序對數,0至n-1組成的序列,太好了!為什麼這樣說?如果第1個數為k,那麼其右邊就有k個數比它小(分別是k-1, k-2, ..., 1, 0),如果最後一個數是k,那麼其左邊就有n-k-1個數比它大(分別是k+1, k+2, ..., n-1)。所以,剛才求出了第一個序列的最小逆序對數後,依次把第1個數放到最後,並統計該序列的逆序對數cnt - a[i] + (n-a[i]-1),更新最小值就是。 [cpp]   #include <cstdio>   #include <cstring>   #include <algorithm>      using namespace std;      const int maxn = 5000 + 10;   int a[maxn], C[maxn], lowerbit[maxn], n;      int sum(int x)      //BIT求前x項和   {       int ret = 0;       while(x > 0)       {           ret += C[x];           x -= lowerbit[x];       }       return ret;   }   void add(int x, int d)      //BIT修改   {       while(x <= n)       {           C[x] += d;           x += lowerbit[x];       }   }   int main()   {       int i;       for(i = 1; i <= maxn; i++) lowerbit[i] = i&(-i);        //打表       while(~scanf("%d", &n))       {           getchar();           for(i = 1; i <= n; i++) scanf("%d", &a[i]);           memset(C, 0, sizeof(C));           int cnt = 0;           for(i = n; i >= 1; i--)       //從後往前           {               cnt += sum(a[i]+1);               add(a[i]+1, 1);           }           int MIN = cnt;           for(i = 1; i <= n; i++)               MIN = min(MIN, cnt = cnt - a[i] + (n-a[i]-1));           printf("%d\n", MIN);       }       return 0;   }    

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved