标签:
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 */
标签:
原文地址:http://www.cnblogs.com/Running-Time/p/4392008.html