1. 程式人生 > >POJ 2299 Ultra-QuickSort(樹狀數組+離散化)

POJ 2299 Ultra-QuickSort(樹狀數組+離散化)

計算 htm upd ace stream max arc clas 下標

http://poj.org/problem?id=2299

題意:
給出一組數,求逆序對。

思路:

這道題可以用樹狀數組解決,但是在此之前,需要對數據進行一下預處理。

這道題目的數據可以大到999,999,999,但數組肯定是無法開這麽大的,但是每組數據最多只有500000個,那麽,怎麽辦呢,離散化!

離散化,也就是將數據和1~n做一一映射。

比如:

9 1 0 5 4

離散化之後變成

5 2 1 4 3

這樣的話,就可以放心的開數組啦!

至於樹狀數組的計算過程,我懶得寫了,直接摘抄一下大神的http://www.cnblogs.com/shenshuyang/archive/2012/07/14/2591859.html

在離散結果中間結果的基礎上,那麽其計算逆序數的過程是這麽一個過程。

1,輸入5,   調用upDate(5, 1),把第5位設置為1

1 2 3 4 5

0 0 0 0 1

計算1-5上比5小的數字存在麽? 這裏用到了樹狀數組的getSum(5) = 1操作,

現在用輸入的下標1 - getSum(5) = 0 就可以得到對於5的逆序數為0。

2. 輸入2, 調用upDate(2, 1),把第2位設置為1

1 2 3 4 5

0 1 0 0 1

計算1-2上比2小的數字存在麽? 這裏用到了樹狀數組的getSum(2) = 1操作,

現在用輸入的下標2 
- getSum(2) = 1 就可以得到對於2的逆序數為1。 3. 輸入1, 調用upDate(1, 1),把第1位設置為1 1 2 3 4 5 1 1 0 0 1 計算1-1上比1小的數字存在麽? 這裏用到了樹狀數組的getSum(1) = 1操作, 現在用輸入的下標 3 - getSum(1) = 2 就可以得到對於1的逆序數為2。 4. 輸入4, 調用upDate(4, 1),把第5位設置為1 1 2 3 4 5 1 1 0 1 1 計算1-4上比4小的數字存在麽? 這裏用到了樹狀數組的getSum(4) = 3操作, 現在用輸入的下標4
- getSum(4) = 1 就可以得到對於4的逆序數為1。 5. 輸入3, 調用upDate(3, 1),把第3位設置為1 1 2 3 4 5 1 1 1 1 1 計算1-3上比3小的數字存在麽? 這裏用到了樹狀數組的getSum(3) = 3操作, 現在用輸入的下標5 - getSum(3) = 2 就可以得到對於3的逆序數為2。 6. 0+1+2+1+2 = 6 這就是最後的逆序數
 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<cstdio>
 5 #include<vector>
 6 #include<queue>
 7 #include<cmath>
 8 #include<map>
 9 #include<stack>
10 using namespace std;
11 
12 const int maxn=500000+5;
13 
14 int n;
15 
16 struct node
17 {
18     int val;
19     int pos;
20 }a[maxn];
21 
22 int b[maxn];
23 int c[maxn];
24 
25 bool cmp(node a,node b)
26 {
27     return a.val<b.val;
28 }
29 
30 int lowbit(int x)
31 {
32     return x&-x;
33 }
34 
35 int sum(int x)
36 {
37     int ret=0;
38     while(x>0)
39     {
40         ret+=c[x];
41         x-=lowbit(x);
42     }
43     return ret;
44 }
45 
46 void add(int x,int d)
47 {
48     while(x<=n)
49     {
50         c[x]+=d;
51         x+=lowbit(x);
52     }
53 }
54 
55 int main()
56 {
57     //freopen("D:\\input.txt","r",stdin);
58     while(~scanf("%d",&n) && n)
59     {
60         for(int i=1;i<=n;i++)
61         {
62             scanf("%d",&a[i].val);
63             a[i].pos=i;
64         }
65         sort(a+1,a+1+n,cmp);
66         for(int i=1;i<=n;i++)
67             b[a[i].pos]=i;
68         memset(c,0,sizeof(c));
69         long long ans=0;
70         for(int i=1;i<=n;i++)
71         {
72             add(b[i],1);
73             ans+=i-sum(b[i]);
74         }
75         printf("%lld\n",ans);
76     }
77     return 0;
78 }

POJ 2299 Ultra-QuickSort(樹狀數組+離散化)