class LRUCache {
public:
int n;
list<pair<int,int>> q;
unordered_map<int,list<pair<int,int>>::iterator> m;
LRUCache(int capacity) : n(capacity) {
}
int get(int key) {
if (m.find(key) == m.end()) return -1;
int value = m[key]->second;
q.erase(m[key]);
q.push_front({key, value});
m[key] = q.begin();
return value;
}
void put(int key, int value) {
if (m.find(key) != m.end()) {
q.erase(m[key]);
} else if (m.size() == n) {
m.erase(q.back().first);
q.pop_back();
}
q.push_front({key, value});
m[key] = q.begin();
}
};
/**
* Your LRUCache object will be instantiated and called as such:
* LRUCache* obj = new LRUCache(capacity);
* int param_1 = obj->get(key);
* obj->put(key,value);
*/
class LFUCache {
public:
int capacity, n = 0, low = 0;
vector<list<pair<int,int>>> q{list<pair<int,int>>()};
unordered_map<int,pair<int,list<pair<int,int>>::iterator>> m;
LFUCache(int capacity): capacity(capacity) {
}
int get(int key) {
if (m.find(key) == m.end()) return -1;
auto [k, it] = m[key];
int value = it->second;
q[k].erase(it);
if (k == low && q[k].empty()) low++;
k++;
if (q.size() == k) q.push_back(list<pair<int,int>>());
q[k].push_front({key, value});
m[key] = {k, q[k].begin()};
return value;
}
void put(int key, int value) {
if (m.find(key) != m.end()) {
auto [k, it] = m[key];
q[k].erase(it);
if (k == low && q[k].empty()) low++;
k++;
if (q.size() == k) q.push_back(list<pair<int,int>>());
q[k].push_front({key,value});
m[key] = {k, q[k].begin()};
return;
}
if (n == capacity) {
auto k = q[low].back().first;
q[low].pop_back();
m.erase(k);
n--;
}
low = 0;
q[low].push_front({key, value});
m[key] = {low, q[low].begin()};
n++;
}
};
/**
* Your LFUCache object will be instantiated and called as such:
* LFUCache* obj = new LFUCache(capacity);
* int param_1 = obj->get(key);
* obj->put(key,value);
*/