More than 2019 cattle off summer school camp (third) - J - LRU management - simulation

https://ac.nowcoder.com/acm/contest/883/J

According to the characteristics of this data structure, which is composed of a computer's cache management LRU algorithm principle which learned, will each visit a query in the cache, the query is successful is called the value of the page and the page is moved to delete the queue tail. Otherwise directly load the page in the tail of the queue is removed, the team's first pop-up when the queue is full. Another operation is to call it, or previous page query to a page, or after a failure both return Invalid.

Then you can delete the middle element of a queue, with a clear chain to achieve, but also to their previous page, next page, it is doubly linked list. Because the list bottleneck that query, and the process of solving the problem can be characterized using other data structures acceleration query. Here is a short string, can be used to maintain the trie unordermap or "character string corresponding to the node list."

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
 
const int maxn = 500010;
const int maxm = 5000010;
const int FAIL = -100;
 
struct ListNode;
 
struct TrieNode {
    TrieNode *ch[10];
    ListNode *lid;
};
 
struct Trie {
    TrieNode tn[maxm], *root;
    int top;
 
    inline void Init() {
        top = 0;
        root = NewNode();
    }
    inline TrieNode *NewNode() {
        for(int i=0;i<10;++i)
            tn[top].ch[i]=nullptr;
        tn[top].lid = nullptr;
        return &tn[top++];
    }
    inline TrieNode *Insert(char *s, ListNode *lid) {
        TrieNode *cur = root;
        int len=strlen(s);
        for(int i = 0; i < len; ++i) {
            int c = s[i] - '0';
            if(!cur->ch[c])
                cur->ch[c] = NewNode();
            cur = cur->ch[c];
        }
        cur->lid = lid;
        return cur;
    }
    inline TrieNode *Query(char *s) {
        TrieNode *cur = root;
        int len=strlen(s);
        for(int i = 0; i < len; ++i) {
            int c = s[i] - '0';
            if(!cur->ch[c])
                return nullptr;
            cur = cur->ch[c];
        }
        return cur;
    }
} T;
 
struct ListNode {
    ListNode *prev, *next;
    int val;
    TrieNode *tid;
};
 
struct List {
    ListNode ln[maxm];
    ListNode *head, *tail;
 
    int top, size;
 
    void Init() {
        //head,tail都是虚拟节点
        top = 0, size = 0;
        head = NewNode(-1, nullptr, nullptr, &ln[1]);
        tail = NewNode(-1, nullptr, &ln[0], nullptr);
    }
 
    ListNode *NewNode(int val, TrieNode *tid, ListNode *prev, ListNode *next) {
        ln[top].val = val;
        ln[top].tid = tid;
        ln[top].prev = prev;
        ln[top].next = next;
        return &ln[top++];
    }
 
    void Append(int val, TrieNode * tid) {
        Insert(val, tid, tail->prev);
    }
 
    void Insert(int val, TrieNode *tid, ListNode *pn) {
        //在pn后面插入
        ListNode *newNode = NewNode(val, tid, pn, pn->next);
        pn->next->prev = newNode;
        pn->next = newNode;
        ++size;
    }
 
    void Delete(ListNode *pn) {
        //删除pn
        pn->prev->next = pn->next;
        pn->next->prev = pn->prev;
        --size;
    }
} L;
 
int M;
char s[105];
 
inline int OP0(int _val) {
    TrieNode *x = T.Query(s);
    int val;
    if(!x||!x->lid) {
        val = _val;
        if(L.size == M) {
            L.head->next->tid->lid = nullptr;
            L.Delete(L.head->next);
        }
        L.Append(val, nullptr);
        L.tail->prev->tid = T.Insert(s, L.tail->prev);
 
    } else {
        ListNode *y = x->lid;
        val = y->val;
        L.Delete(y);
        L.Append(val, x);
        x->lid = L.tail->prev;
    }
    return val;
}
 
inline int OP1(int _val) {
    TrieNode *x = T.Query(s);
    if(!x)
        return FAIL;
    ListNode *y = x->lid;
    if(!y)
        return FAIL;
    if(_val > 0) {
        y = y->next;
        if(y == L.tail)
            return FAIL;
        return y->val;
    }
    if(_val < 0) {
        y = y->prev;
        if(y == L.head)
            return FAIL;
        return y->val;
    }
    return y->val;
}
 
int main() {
#ifdef local
    freopen("a.txt", "r", stdin);
#endif // Yinku
    int t, q, op, v;
    scanf("%d", &t);
    while(t--) {
        T.Init();
        L.Init();
        scanf("%d%d", &q, &M);
        for(int i = 0; i < q; ++i) {
            scanf("%d%s%d", &op, s, &v);
            if(!op)
                printf("%d\n", OP0(v));
            else {
                int ans = OP1(v);
                if(ans == FAIL)
                    puts("Invalid");
                else
                    printf("%d\n", ans);
            }
        }
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/Yinku/p/11250182.html