码迷,mamicode.com
首页 > 其他好文 > 详细

逆序数 POJ 2299 Ultra-QuickSort

时间:2015-04-04 13:33:48      阅读:255      评论:0      收藏:0      [点我收藏+]

标签:

 

题目传送门

  1 /*
  2     暴力 超时
  3 */
  4 #include <stdio.h>
  5 
  6 const int MAX_N = 500000;
  7 int a[MAX_N+10];
  8 long long cnt = 0;
  9 
 10 int main(void)
 11 {
 12     //freopen ("inD.txt", "r", stdin);
 13     int n;
 14     
 15     while (scanf ("%d", &n) != EOF && n)
 16     {
 17         for (int i=1; i<=n; ++i)
 18         {
 19             scanf ("%d", &a[i]);
 20         }
 21 
 22         for (int i=1; i<=n; ++i)
 23         {
 24             for (int j=i+1; j<=n; ++j)
 25             {
 26                 if (a[i] > a[j])
 27                     cnt++;
 28             }
 29         }
 30         printf ("%lld\n", cnt);
 31         cnt = 0;
 32     }
 33     
 34     return 0;
 35 }
 36 
 37 /* 
 38     题目的意思就是要求冒泡排序的交换次数。 
 39     所用的算法:用归并排序,求逆序数的个数。
 40 
 41     归并排序是将数列a[p, r]分成两半a[p, q]和a[q+1,r]分别进行归并排序,
 42     然后再将这两半合并起来。在合并的过程中(设p<=i<=q,q+1<=j<=r),
 43     当L[i]<=R[j]时,并不产生逆序数;
 44     当L[i]>R[j]时,在前半部分中比L[i]大的数都比R[j]大,
 45     将R[j]放在L[i]前面的话,逆序数要加上q+1-i。
 46     因此,可以在归并排序中的合并过程中计算逆序数。 
 47  
 48     这道题充分印证了,即使merge本身可能用的不多,但分冶的思想却是无所不在 
 49 
 50 */
 51 #include <stdio.h>
 52 
 53 const int MAX_N = 500000;
 54 int a[MAX_N+10];
 55 long long cnt = 0;
 56 
 57 const int INF = 0xffffff; 
 58  
 59 void Merge(int *a, int p, int q, int r)
 60 {
 61     int n1 = q - p + 1;
 62     int n2 = r - q;
 63     int L[MAX_N/2+1], R[MAX_N/2+1];
 64     int i, j;
 65     for (i=1; i<=n1; ++i)
 66     {
 67         L[i] = a[p+i-1];
 68     }
 69     for (j=1; j<=n2; ++j)
 70     {
 71         R[j] = a[q+j];
 72     }
 73     L[n1+1] = INF;    R[n2+1] = INF;
 74     i = 1;    j = 1;
 75     for (int k=p; k<=r; ++k)
 76     {
 77         if (L[i] <= R[j])
 78         {
 79             a[k] = L[i];
 80             i++;
 81         }
 82         else
 83         {
 84             a[k] = R[j];
 85             ++j;
 86             cnt += n1 - i + 1;         //此步骤是在归并排序法中加的一句,用来计数求逆序数的数目
 87 
 88         }
 89     }
 90 }
 91 
 92 void MergeSort(int *a, int p, int r)
 93 {
 94     int q;
 95     
 96     if (p < r)
 97     {
 98         q = (p + r) / 2;
 99         MergeSort (a, p, q);
100         MergeSort (a, q+1, r);
101         Merge (a, p, q, r);
102     }
103 }
104 
105 int main(void)        //POJ 2299 Ultra-QuickSort
106 {
107     //freopen ("inD.txt", "r", stdin);
108     int n;
109     
110     while (scanf ("%d", &n) != EOF && n)
111     {
112         for (int i=1; i<=n; ++i)
113         {
114             scanf ("%d", &a[i]);
115         }
116         MergeSort (a, 1, n);
117         printf ("%lld\n", cnt);
118         cnt = 0;
119     }
120     
121     return 0;
122 }
123 
124 /*
125     线段树-单点更新
126 */
127 #include <cstdio>
128 #include <algorithm>
129 #define lson l, m, rt << 1
130 #define rson m+1, r, rt << 1 | 1
131 using namespace std;
132 
133 const int MAX_N = 500000;
134 const int INF = 0x3f3f3f3f;
135 int a[MAX_N];
136 int b[MAX_N];
137 int sum[MAX_N << 2];
138 
139 void pushup(int rt)
140 {
141     sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
142 }
143 
144 void build(int l, int r, int rt)
145 {
146     sum[rt] = 0;
147     if (l == r) return ;
148     int m = (l + r) >> 1;
149     build (lson);
150     build (rson);
151 
152     pushup (rt);
153 }
154 
155 void update(int p, int l, int r, int rt)
156 {
157     if (l == r)
158     {
159         sum[rt]++;      //记录次数
160         return ;
161     }
162     int m = (l + r) >> 1;
163     if (p <= m)
164     {
165         update (p, lson);
166     }
167     else
168         update(p, rson);
169     pushup (rt);
170 }
171 
172 int query(int ql, int qr, int l, int r, int rt)
173 {
174     if (ql <= l && r <= qr)
175     {
176         return sum[rt];
177     }
178     int m = (l + r) >> 1;
179     int ans = 0;
180     if (ql <= m)    ans += query (ql, qr, lson);
181     if (qr > m)     ans += query (ql, qr, rson);
182 
183     return ans;
184 }
185 
186 int BinarySearch(int key, int l, int r)
187 {
188     while (r >= l)
189     {
190         int mid = (l + r) >> 1;
191         if (key == b[mid])    return mid;
192         if (key < b[mid])    r = mid - 1;
193         else    l = mid + 1;
194     }
195 }
196 
197 int main(void)
198 {
199     //freopen ("inD.txt", "r", stdin);
200     int n;
201     while (~scanf ("%d", &n) && n)
202     {
203         build (0, n-1, 1);
204         
205         for (int i=1; i<=n; ++i)   
206         {
207             scanf ("%d", &a[i]);
208             b[i] = a[i];
209         }
210         sort (b+1, b+n+1);
211         long long ans = 0;
212         for (int i=1; i<=n; ++i)
213         {
214             int x = BinarySearch (a[i], 1, n);
215             ans += query (x, n, 1, n, 1);
216             update (x, 1, n, 1);
217         }
218         printf ("%lld\n", ans);
219     }
220 
221     return 0;
222 }
223 
224 /*
225     树状数组
226 */

 

逆序数 POJ 2299 Ultra-QuickSort

标签:

原文地址:http://www.cnblogs.com/Running-Time/p/4392008.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!