import java.util.*;


public class Solution {
    static class Node{
        int freq;
        int key;
        int val;
        public Node(int freq, int key, int val){
            this.freq = freq;
            this.key = key;
            this.val = val;
        }
    }
    //频率--链表的哈希表
    //相同频率的数据对应一个链表LinkedList,最先添加的在头部
    private Map<Integer, LinkedList<Node>> freq_mq = new HashMap<>();
    //key到节点Node的哈希表
    //记录每个key对应的节点,当存取值时取出Node的频率,根据频率取出对应的链表,移除当前Node,将Node添加到更高频次的链表中
    private Map<Integer, Node> mp = new HashMap<>();
    //记录缓存剩余容量
    private int size = 0;
    //记录最小频次
    private int min_freq = 0;
    /**
     * lfu design
     * @param operators int整型二维数组 ops
     * @param k int整型 the k
     * @return int整型一维数组
     */
    public int[] LFU (int[][] operators, int k) {
        // write code here
        //operators
        this.size = k;
        //每个操作里面,第一个是取数据操作数
        int len = (int)Arrays.stream(operators).filter(x -> x[0] == 2).count();
        int[] res = new int[len];
        for(int i = 0, j = 0; i< operators.length; i++){
            if(operators[i][0] == 1){
                //set操作
                set(operators[i][1], operators[i][2]);
            }else{
                //get
                res[j++] = get(operators[i][1]);
            }
        }
        return res;
    }
    private void set(int key, int value){
        if(mp.containsKey(key)){
            //存在就 更新频率和节点值
            update(mp.get(key), key, value);
        }else{
            //哈希表中没有
            if(size == 0){
                //剩余容量没了
                int oldKey = freq_mq.get(min_freq).getLast().key;
                freq_mq.get(min_freq).removeLast();
                if(freq_mq.get(min_freq).isEmpty()){
                    freq_mq.remove(min_freq);
                }
                mp.remove(oldKey);
            }else{
                si***_freq = 1;
            if(!freq_mq.containsKey(1)){
                freq_mq.put(1, new LinkedList<Node>());
            }
            freq_mq.get(1).addFirst(new Node(1, key, value));
            mp.put(key, freq_mq.get(1).getFirst());
        }
    }
    private void update(Node node ,int key, int value){
        //找到频率
        int freq = node.freq;
        //原频率中删除该节点,因为频率变了
        freq_mq.get(freq).remove(node);
        //表中当前频率的数据没有了,直接清除,如果freq是最小频率,那么最小频率编程了min_freq+1
        if(freq_mq.get(freq).isEmpty()){
            freq_mq.remove(freq);
            if(min_freq == freq){
                min_freq ++;
            }
        }
        //插入频率 + 1的范围中
        if(!freq_mq.containsKey(freq + 1)){
            freq_mq.put(freq + 1 , new LinkedList<Node>());
        }
        //插入频率加1的链表里
        freq_mq.get(freq + 1).addFirst(new Node(1, key, value));
        mp.put(key, freq_mq.get(freq+1).getFirst());
    }
    private int get(int key){
        int res = -1;
        if(mp.containsKey(key)){
            Node node = mp.get(key);
            res = node.val;
            //更新频率
            update(node, key, res);
        }
        return res;
    }
}