forked from kamyu104/LeetCode-Solutions
-
Notifications
You must be signed in to change notification settings - Fork 0
/
design-most-recently-used-queue.cpp
115 lines (101 loc) · 2.84 KB
/
design-most-recently-used-queue.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
// Time: ctor: O(n + m), m is the max number of calls
// Space: fetch: O(log(n + m))
class MRUQueue {
public:
MRUQueue(int n)
: bit_{n}
, curr_{n} {
for (int i = 0; i < n; ++i) {
lookup_[i] = i + 1;
}
}
int fetch(int k) {
int pos = bit_.binary_lift(k);
int val = lookup_[pos];
lookup_.erase(pos);
bit_.add(pos, -1);
bit_.add(curr_, 1);
lookup_[curr_++] = val;
return val;
}
private:
class BIT {
public:
static const int MAX_CALLS = 2000;
BIT(int n) : bit_(n + MAX_CALLS + 1) { // 0-indexed
for (int i = 1; i < size(bit_); ++i) {
bit_[i] = ((i - 1 < n) ? 1 : 0) + bit_[i - 1];
}
for (int i = size(bit_) - 1; i >= 1; --i) {
int last_i = i - lower_bit(i);
bit_[i] -= bit_[last_i];
}
}
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;
}
int binary_lift(int k) const {
int total = 0;
int pos = 0;
for (int i = floor_log2_x(size(bit_) - 1); i >= 0; --i) {
if (pos + (1 << i) < size(bit_) && !(total + bit_[pos + (1 << i)] >= k)) {
total += bit_[pos + (1 << i)];
pos += (1 << i);
}
}
return (pos + 1) - 1;
}
private:
int lower_bit(int i) const {
return i & -i;
}
int floor_log2_x(int x) const {
return 8 * sizeof(int) - __builtin_clz(x) - 1;
};
vector<int> bit_;
};
BIT bit_;
unordered_map<int, int> lookup_;
int curr_;
};
// Time: ctor: O(n)
// Space: fetch: O(sqrt(n))
// sqrt decomposition solution
class MRUQueue2 {
public:
MRUQueue2(int n)
: buckets_(ceil(sqrt(n))) {
for (int i = 0; i < n; ++i) {
buckets_[i / size(buckets_)].emplace_back(i + 1);
}
}
int fetch(int k) {
--k;
int left = k / size(buckets_);
int idx = k % size(buckets_);
auto cit = cbegin(buckets_[left]);
advance(cit, idx);
int val = *cit;
buckets_[left].erase(cit);
buckets_.back().emplace_back(val);
for (int i = size(buckets_) - 2; i >= left; --i) {
int x = buckets_[i + 1].front();
buckets_[i + 1].pop_front();
buckets_[i].emplace_back(x);
}
return val;
}
private:
vector<list<int>> buckets_;
};