-
Notifications
You must be signed in to change notification settings - Fork 3
/
Algorithm.h
446 lines (436 loc) · 12.1 KB
/
Algorithm.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
#pragma once
#include <functional>
#include <ratio>
#include <string>
#include <cstdlib>
#include <cstring>
namespace ds
{
template<typename Iter>
Iter next(Iter it) { return ++it; }
template<typename Iter>
Iter prev(Iter it) { return --it; }
//返回第一个>=val的,也即是第一个满足!comp(*where,val)的where
template<typename Iter, typename T, typename Comp>
Iter lower_bound(Iter first, Iter last, const T &val, Comp comp)
{
--last;
while (first <= last)
{
Iter mid = first + (last - first) / 2;
if (comp(*mid, val))
first = mid + 1;
else
last = mid - 1;
}
return first;
}
template<typename Iter, typename T>
Iter lower_bound(Iter first, Iter last, const T &val)
{
return ds::lower_bound(first, last, val, std::less<T>());
}
//返回第一个>val的,也即是第一个满足comp(val,*where)的where
template<typename Iter, typename T, typename Comp>
Iter upper_bound(Iter first, Iter last, const T &val, Comp comp)
{
--last;
while (first <= last)
{
Iter mid = first + (last - first) / 2;
if (comp(val, *mid))
last = mid - 1;
else
first = mid + 1;
}
return first;
}
template<typename Iter, typename T>
Iter upper_bound(Iter first, Iter last, const T &val)
{
return ds::upper_bound(first, last, val, std::less<T>());
}
//返回第一个满足check的,假定前半段不满足而后半段满足
template<typename Iter, typename Check>
Iter bisearch(Iter first, Iter last, Check check)
{
while (first <= last)
{
Iter mid = first + (last - first) / 2;
if (check(*mid))
last = mid - 1;
else
first = mid + 1;
}
return first;
}
template<typename Check>
int bisearch(int first, int last, Check check)
{
while (first <= last)
{
int mid = first + (last - first) / 2;
if (check(mid))
last = mid - 1;
else
first = mid + 1;
}
return first;
}
//注:stl的push_heap假定[first,last-1)为合法堆,push的新值是last-1
//pop_heap假定[first,last)为合法堆,pop出来的值放在last-1
template<typename Iter, typename Comp>
void fixHeap_(Iter first, Comp comp, int where, int heapSize)//有且仅有where及其孩子违反堆性质,修复之
{
int nxt = (where << 1) + 1;
auto value = std::move(*(first + where));
while (nxt < heapSize)
{
if (nxt + 1 < heapSize && comp(*(first + nxt), *(first + nxt + 1)))
++nxt;
if (comp(value, *(first + nxt)))
{
*(first + where) = *(first + nxt);
where = nxt;
nxt = (where << 1) + 1;;
}
else
break;
}
*(first + where) = value;
}
template<typename Iter, typename Comp>
void push_heap(Iter first, Iter last, Comp comp) //[first,last-1)为合法堆,push的新值是last-1
{
//stl实现,不用swap而是用赋值,稍微快一些
auto value = std::move(*(last - 1));
int hole = last - first - 1;//刚刚被move的下标
int parent = (hole - 1) >> 1;
while (hole && comp(*(first + parent), value))//value一直在向上浮动
{
*(first + hole) = std::move(*(first + parent));
hole = parent;
parent = (hole - 1) >> 1;
}
*(first + hole) = std::move(value);
}
template<typename Iter>
void push_heap(Iter first, Iter last)
{
push_heap(first, last, std::less<typename std::iterator_traits<Iter>::value_type >());
}
template<typename Iter, typename Comp>
void heapSort(Iter first, Iter last, Comp comp)
{
int heapSize = last - first;
for (int i = heapSize >> 1; i >= 0; --i)
fixHeap_(first, comp, i, heapSize);
while (heapSize)
{
std::swap(*first, *(first + --heapSize));
fixHeap_(first, comp, 0, heapSize);
}
}
template<typename Iter>
void heapSort(Iter first, Iter last)
{
ds::heapSort(first, last, std::less<typename std::iterator_traits<Iter>::value_type>());
}
template <typename Iter, typename T, typename Comp>
Iter partion(Iter first, Iter last, const T &pivot, Comp comp)
{
while (true)
{
while (comp(*first, pivot))
++first; //找出第一个>=pivot的first
--last;
while (comp(pivot, *last))
--last; //找出第一个(倒着数)<=pivot的last
if (first >= last)
return first;
std::swap(*first, *last);
++first; //swap完了之后first指向的位置已经保证<=pivot,last同理
//但是对last的修改在下一轮循环中进行,可以避免特判last是不是尾后迭代器
}
}
template <typename T, typename Comp>
T median_(const T& a, const T& b, const T& c, Comp comp)
{
if (comp(a, b))// a<b
{
if (comp(b, c)) //a<b<c
return b;
if (comp(a, c))
return c;
return a;
}
//a>=b
if (comp(a, c)) //b<=a<c
return a;
if (comp(b, c))
return c;
return b;
}
inline int lg_(int x)
{
int ret = 0;
for (; x; x >>= 1, ++ret);
return ret;
}
template <typename Iter, typename Comp>
void introSort_(Iter first, Iter last, Comp comp, int depth)
{
if (last - first <= 16)
return;
if (!depth)
{
heapSort(first, last, comp);
return;
}
const auto &pivot = median_(*first, *(first + (last - first) / 2), *(last - 1), comp);
Iter div = partion(first, last, pivot, comp);
introSort_(first, div, comp, depth - 1);
introSort_(div, last, comp, depth - 1);
}
template <typename Iter, typename Comp>
void insertSort(Iter first, Iter last, Comp comp)
{
Iter cur = first + 1;
while (cur != last)
{
Iter tmp = cur++;
auto value = std::move(*tmp);
if (comp(value,*first)) //首先与第一个比较,如果比第一个还小,那么直接移动
{
while (tmp != first) //这里就不用判断大小了
*tmp = std::move(*(tmp - 1)), --tmp;
*tmp = std::move(value);
continue;
}
//这里就不用判断越界了
while (comp(value, *(tmp - 1)))
*tmp = std::move(*(tmp - 1)), --tmp;
*tmp = std::move(value);
}
}
template<typename Iter, typename Comp>
void sort(Iter first, Iter last, Comp comp)
{
if (last - first <= 1)
return;
introSort_(first, last, comp, 2 * lg_(last - first));
insertSort(first, last, comp);
}
template<typename Iter>
void sort(Iter first, Iter last)
{
ds::sort(first, last, std::less<typename std::iterator_traits<Iter>::value_type>());
}
template<typename Iter, typename Comp>
void merge(Iter first, Iter mid, Iter last, Comp comp, typename std::iterator_traits<Iter>::value_type* aux = nullptr) //归并[firts,mid)和[mid,last)并置于[)
{
typedef typename std::iterator_traits<Iter>::value_type value_type;
first = ds::upper_bound(first, mid, *mid, comp); //所有<=*mid的都不用移动
const bool naux = !aux;
if (naux)
aux = new value_type[last - first];
Iter tmpmid = mid, tmpfirst = first;
int pos = 0;
while (first != tmpmid && mid != last)
{
if (comp(*mid, *first)) //稳定
aux[pos++] = std::move(*(mid++));
else
aux[pos++] = std::move(*(first++));
}
while (first != tmpmid) aux[pos++] = std::move(*(first++));
pos = 0;
for (; tmpfirst != mid; ++tmpfirst, ++pos)
*tmpfirst = std::move(aux[pos]);
if (naux)
delete[]aux;
}
template<typename Iter>
void merge(Iter first, Iter mid, Iter last)
{
ds::merge(first, mid, last, std::less<>());
}
template<typename Iter, typename Comp>
void stable_sort_impl1_(Iter first, Iter last, Comp comp)
{
const int len = last - first;
if (len <= 1)
return;
typedef std::pair<typename std::iterator_traits<Iter>::value_type, int> SortPair;
//核心思想:假装我没有动过对象
SortPair *aux = (SortPair*)malloc((last - first) * sizeof(SortPair));
for (int i = 0; i < len; ++i, ++first)
new(aux + i) SortPair(std::move(*first), i + 0);//确保调用pair的两个参数都是右值引用的构造函数
auto nComp = [comp](const SortPair &lhs, const SortPair &rhs) ->bool
{
if (comp(lhs.first, rhs.first))
return true;
if (comp(rhs.first, lhs.first))
return false;
return lhs.second < rhs.second;
};
ds::sort(aux, aux + len, nComp);
--last;
for (int i = len - 1; i >= 0; --i, --last) //仅仅是因为懒得存first,所以用一下last
*last = std::move(aux[i].first);
free(aux);//pair不需要析构
}
template<typename Iter, typename Comp>
void merge_sort_impl_(Iter first, Iter last, Comp comp, typename std::iterator_traits<Iter>::pointer aux)
{
if (last - first <= 16)
{
ds::insertSort(first, last, comp);
return;
}
const Iter m = first + (last - first) / 2;
merge_sort_impl_(first, m, comp, aux);
merge_sort_impl_(m, last, comp, aux);
ds::merge(first, m, last, comp, aux);
}
template<typename Iter, typename Comp>
void stable_sort_impl2_(Iter first, Iter last, Comp comp)
{
typedef typename std::iterator_traits<Iter>::value_type value_type;
const Iter mid = first + (last - first) / 2;
value_type *aux = new value_type[last - first];
ds::merge_sort_impl_<Iter, Comp>(first, mid, comp, aux);
ds::merge_sort_impl_<Iter, Comp>(mid, last, comp, aux);
ds::merge(first, mid, last, comp, aux);
delete[]aux;
}
template<typename Iter>
void stable_sort(Iter first, Iter last)
{
ds::stable_sort_impl2_(first, last, std::less<>());
}
inline void radixSort(int *first, int *last)
{
//只排正数,不管负数
const static int U = 65536;
static int cnt[U];
auto mask = [](int x, int d) {return (x >> (d * 16))&(U - 1); };
const int len = last - first;
int *tmp = new int[len];
for (int d = 0; d<2; ++d)
{
memset(cnt, 0, sizeof(cnt));
for (int i = 0; i < len; ++i)
++cnt[mask(first[i], d)];
for (int i = 1; i < U; ++i)
cnt[i] += cnt[i - 1];
for (int i = len - 1; i >= 0; --i)//逆序,保证稳定
tmp[--cnt[mask(first[i], d)]] = first[i];//cnt[mask(first[i], d)-1即是first[i]"应该放置"的位置
memcpy(first, tmp, len * sizeof(int));
}
delete[]tmp;
}
template <typename Iter, typename Equal>
Iter unique(Iter first, Iter last, Equal equal)
{
Iter uni = first;
while (first != last)
{
if (equal(*first, *uni))
++first;
else
*(++uni) = *(first++);
}
return ++uni;
}
template <typename Iter>
Iter unique(Iter first, Iter last)
{
return ds::unique(first, last, std::equal_to<typename std::iterator_traits<Iter>::value_type>());
}
template <typename Iter>
void reverse(Iter first, Iter last)
{
--last;
while (true)
{
if (first == last)
return;
std::swap(*(first++), *(last--));
if (prev(first) == last)
return;
}
}
template <typename Iter, typename Comp>
Iter rangeMax(Iter first, Iter last, Comp comp)
{
Iter maxIter = first;
while (first != last)
{
if (comp(*maxIter, *first))
maxIter = first;
++first;
}
return maxIter;
}
template <typename Iter>
Iter rangeMax(Iter first, Iter last)
{
return rangeMax(first, last, std::less<typename std::iterator_traits<Iter>::value_type>());
}
template <typename Iter, typename Comp>
Iter rangeMin(Iter first, Iter last, Comp comp)
{
Iter minIter = first;
while (first != last)
{
if (comp(*first, *minIter))
minIter = first;
++first;
}
return minIter;
}
template <typename Iter>
Iter rangeMin(Iter first, Iter last)
{
return rangeMin(first, last, std::less<typename std::iterator_traits<Iter>::value_type>());
}
template <typename Iter, typename Comp>
bool next_permutation(Iter first, Iter last, Comp comp)
{
//从后向前找,找到第一个下降元素(倒着找的意义上的下降),如找不到证明整个数列降序排列,无下一排列
//将该元素与(该元素,last)间的最后一个(正序意义)小于该元素的元素交换,再将(用来换的元素,last)反向
Iter bound = last;
while (--last != first)
if (comp(*prev(last), *last))
{
Iter firstDescend = prev(last);
Iter lastGreater = bound;
while (!(comp(*firstDescend, *--lastGreater)));
std::swap(*firstDescend, *lastGreater);
ds::reverse(last, bound);
return true;
}
ds::reverse(first, bound);
return false;
}
template <typename Iter>
bool next_permutation(Iter first, Iter last)
{
return ds::next_permutation(first, last, std::less<typename std::iterator_traits<Iter>::value_type>());
}
template<typename K>
void bitwiseSwap(K *lhs,K *rhs) noexcept
{
//这并不是什么奇技淫巧,也完全没有UB(只要不拿来swap带虚函数表的)
//主要是为了避免忘记swap某些成员
char *cl = reinterpret_cast<char *>(lhs), *cr = reinterpret_cast<char *>(rhs);
int bit = sizeof(K);
while (bit--)
{
char tmp = *cl;
*cl++ = *cr;
*cr++ = tmp;
}
}
}