class Node implements Comparable<Node>{
public int key;
public int value;
public int lastTime;
public int fre;
public Node(int key,int value,int lastTime){
this.key=key;
this.value=value;
this.lastTime = lastTime;
this.fre=1;
}
@Override
public int compareTo(Node o) {
if(this.fre!=o.fre){
//System.out.println(this.key+"++++fre:"+this.fre);
//System.out.println(o.key+"+++++fre"+o.fre);
//System.out.println(Integer.compare(o.fre,this.fre));
return Integer.compare(this.fre,o.fre);
}
//System.out.println(this.key+"---"+this.value);
//System.out.println(o.key+"----"+o.value);
//System.out.println(-Integer.compare(this.lastTime,o.lastTime));
return Integer.compare(this.lastTime,o.lastTime);
}
public void setValue(int value,int lastTime) {
this.value=value;
this.lastTime=lastTime;
this.fre++;
}
public int getValue(int lastTime) {
this.lastTime=lastTime;
this.fre++;
return value;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Node node = (Node) o;
return key == node.key;
}
@Override
public int hashCode() {
return Objects.hash(key, value);
}
}
class LFUCache {
public int capacity;
public int time;
public HashMap<Integer,Node> values;
public TreeSet<Node> keys;
public LFUCache(int capacity) {
time=0;
this.capacity=capacity;
values = new HashMap<Integer, Node>();
keys = new TreeSet<Node>();
}
public int get(int key) {
if(capacity==0) return -1;
if(values.containsKey(key)){
Node oldN = values.get(key);
keys.remove(oldN);
int ans = oldN.getValue(++time);
keys.add(oldN);
return ans;
}
else return -1;
}
public void put(int key, int value) {
if(capacity==0) return;
if(values.containsKey(key)){
Node oldN = values.get(key);
keys.remove(oldN);
oldN.setValue(value,++time);
keys.add(oldN);
}else{
if(values.size()==this.capacity) {
Node n = values.get(keys.first().key);
values.remove(n.key);
keys.remove(n);
}
Node s = new Node(key,value,++time);
values.put(key,s);
keys.add(s);
}
}
}