forked from kamyu104/LeetCode-Solutions
-
Notifications
You must be signed in to change notification settings - Fork 0
/
create-sorted-array-through-instructions.cpp
131 lines (120 loc) · 4.17 KB
/
create-sorted-array-through-instructions.cpp
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
// Time: O(nlogm)
// Space: O(m)
class Solution {
public:
int createSortedArray(vector<int>& instructions) {
static const int MOD = 1e9 + 7;
BIT bit(*max_element(cbegin(instructions), cend(instructions)));
int result = 0;
for (int i = 0; i < size(instructions); ++i) {
const auto inst = instructions[i] - 1;
auto cost = min(bit.query(inst - 1), i - bit.query(inst));
if (MOD - result <= cost) {
cost -= MOD;
}
result += cost;
bit.add(inst, 1);
}
return result;
}
private:
class BIT {
public:
BIT(int n) : bit_(n + 1) { // 0-indexed
}
void add(int i, int val) {
++i;
for (; i < size(bit_); i += lower_bit(i)) {
bit_[i] += val;
}
}
int query(int i) const {
++i;
int total = 0;
for (; i > 0; i -= lower_bit(i)) {
total += bit_[i];
}
return total;
}
private:
int lower_bit(int i) const {
return i & -i;
}
vector<int> bit_;
};
};
// Time: O(nlogn)
// Space: O(n)
// in fact, we could use a raw array instead of vector to avoid TLE
class Solution_TLE {
public:
int createSortedArray(vector<int>& instructions) {
static const int MOD = 1e9 + 7;
vector<int> smaller_counts(size(instructions)), larger_counts(size(instructions));
vector<pair<int, int>> smaller_idxs, larger_idxs;
for (int i = 0; i < size(instructions); ++i) {
smaller_idxs.emplace_back(instructions[i], i);
larger_idxs.emplace_back(instructions[i], i);
}
smallerMergeSort(&smaller_idxs, 0, size(smaller_idxs) - 1, &smaller_counts);
largerMergeSort(&larger_idxs, 0, size(larger_idxs) - 1, &larger_counts);
int result = 0;
for (int i = 0; i < size(instructions); ++i) {
auto cost = min(smaller_counts[i], larger_counts[i]);
if (MOD - result <= cost) {
cost -= MOD;
}
result += cost;
}
return result;
}
private:
void smallerMergeSort(vector<pair<int, int>> *idxs, int start, int end, vector<int> *counts) {
if (end - start <= 0) { // The number of range [start, end] of which size is less than 2 doesn't need sort.
return;
}
int mid = start + (end - start) / 2;
smallerMergeSort(idxs, start, mid, counts);
smallerMergeSort(idxs, mid + 1, end, counts);
int r = start;
vector<pair<int, int>> tmp;
for (int i = mid + 1; i <= end; ++i) {
// Merge the two sorted arrays into tmp.
while (r <= mid && (*idxs)[r].first < (*idxs)[i].first) {
tmp.emplace_back((*idxs)[r++]);
}
tmp.emplace_back((*idxs)[i]);
(*counts)[(*idxs)[i].second] += r - start;
}
while (r <= mid) {
tmp.emplace_back((*idxs)[r++]);
}
// Copy tmp back to num_idxs.
copy(tmp.begin(), tmp.end(), idxs->begin() + start);
}
void largerMergeSort(vector<pair<int, int>> *idxs, int start, int end, vector<int> *counts) {
if (end - start <= 0) { // The number of range [start, end] of which size is less than 2 doesn't need sort.
return;
}
int mid = start + (end - start) / 2;
largerMergeSort(idxs, start, mid, counts);
largerMergeSort(idxs, mid + 1, end, counts);
int r = start;
vector<pair<int, int>> tmp;
for (int i = mid + 1; i <= end; ++i) {
// Merge the two sorted arrays into tmp.
while (r <= mid && (*idxs)[r].first <= (*idxs)[i].first) {
tmp.emplace_back((*idxs)[r++]);
}
if (r <= mid) {
tmp.emplace_back((*idxs)[i]);
}
(*counts)[(*idxs)[i].second] += mid - r + 1;
}
while (r <= mid) {
tmp.emplace_back((*idxs)[r++]);
}
// Copy tmp back to num_idxs.
copy(tmp.begin(), tmp.end(), idxs->begin() + start);
}
};