2019牛客暑期多校训练营(第三场) - J - LRU management - 模拟
https://ac.nowcoder.com/acm/contest/883/J
根据这个数据结构的特点,也就是计算机组成原理里面学过的cache的LRU管理算法,每次访问都会在cache中查询一页,查询成功则调用该页的值并将该页移动到删除队列的尾部。否则直接加载该页在删除队列的尾部,当队列满时弹出队首。另一种操作是查询到某页后调用其、或其前一页、或其后一页,失败均返回Invalid。
那么一个可以删除中间元素的队列,明显用链表实现,而且要其前一页、后一页,那就双向链表。因为链表的瓶颈在于查询,而这道题的特点可以使用其他数据结构加速查询的过程。这里都是短的字符串,可以用unordermap或者trie来维护“字符串对应的链表节点”。
#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;
}
2019牛客暑期多校训练营(第三场) - J - LRU management - 模拟的更多相关文章
- 2019牛客暑期多校训练营(第三场)H题目
题意:给你一个N×N的矩阵,求最大的子矩阵 满足子矩阵中最大值和最小值之差小于等于m. 思路:这题是求满足条件的最大子矩阵,毫无疑问要遍历所有矩阵,并判断矩阵是某满足这个条件,那么我们大致只要解决两个 ...
- 2019牛客暑期多校训练营(第三场)- F Planting Trees
题目链接:https://ac.nowcoder.com/acm/contest/883/F 题意:给定n×n的矩阵,求最大子矩阵使得子矩阵中最大值和最小值的差值<=M. 思路:先看数据大小,注 ...
- 2019牛客暑期多校训练营(第三场) F.Planting Trees(单调队列)
题意:给你一个n*n的高度矩阵 要你找到里面最大的矩阵且最大的高度差不能超过m 思路:我们首先枚举上下右边界,然后我们可以用单调队列维护一个最左的边界 然后计算最大值 时间复杂度为O(n*n*n) # ...
- 2019牛客暑期多校训练营(第六场)J Upgrading Technology
传送门 题意: 就是给你n个技能,每个技能最高升到m级,每升一级就是耗费Cij钱,这个Cij可能是负的,如果所有技能都升到或者说超过j等级,就会获得Dj钱,这个Dj也有可能是负值,让你求你最多得到多少 ...
- 2019牛客暑期多校训练营(第九场)A:Power of Fibonacci(斐波拉契幂次和)
题意:求Σfi^m%p. zoj上p是1e9+7,牛客是1e9: 对于这两个,分别有不同的做法. 前者利用公式,公式里面有sqrt(5),我们只需要二次剩余求即可. 后者mod=1e9,5才 ...
- 2019牛客暑期多校训练营(第一场)A题【单调栈】(补题)
链接:https://ac.nowcoder.com/acm/contest/881/A来源:牛客网 题目描述 Two arrays u and v each with m distinct elem ...
- 2019牛客暑期多校训练营(第一场) B Integration (数学)
链接:https://ac.nowcoder.com/acm/contest/881/B 来源:牛客网 Integration 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 5242 ...
- 2019牛客暑期多校训练营(第一场) A Equivalent Prefixes ( st 表 + 二分+分治)
链接:https://ac.nowcoder.com/acm/contest/881/A 来源:牛客网 Equivalent Prefixes 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/ ...
- 2019牛客暑期多校训练营(第二场)F.Partition problem
链接:https://ac.nowcoder.com/acm/contest/882/F来源:牛客网 Given 2N people, you need to assign each of them ...
- 2019牛客暑期多校训练营(第一场)A Equivalent Prefixes(单调栈/二分+分治)
链接:https://ac.nowcoder.com/acm/contest/881/A来源:牛客网 Two arrays u and v each with m distinct elements ...
随机推荐
- linux下实现web数据同步的四种方式(性能比较)
实现web数据同步的四种方式 ======================================= 1.nfs实现web数据共享2.rsync +inotify实现web数据同步3.rsyn ...
- 【python基础】集合方法汇总
一.定义 用于存储一组无序的不重复的数据 二.特点 1. 集合是无序的 2.集合中的元素是不重复的, 唯一的 3.集合中存储的数据必须是不可变的数据类型 4.集合是可变的数据类型 三.语法 set1 ...
- 网络编程基础-socket的简单实用
目录 1.软件开发架构 客户端与服务端的作用 C/S架构: B/S架构: 2.网络编程 3.互联网协议 socket: socket的具体工作流程: socket(套接字)的内置方法 1.软件开发架构 ...
- LeetCode--064--最小路径和
给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小. 说明:每次只能向下或者向右移动一步. 示例: 输入:[ [1,3,1], [1,5,1], ...
- SpringBoot自定义FailureAnalyzer
官网说明 1.1 创建自己的 FailureAnalyzer FailureAnalyzer是一种在启动时拦截 exception 并将其转换为 human-readable 消息的好方法,包含在故障 ...
- CopyOnWrite 个人理解以及应用
缘由 最近在看<Redis 设计与实现>,看到Redis的执行bgsave生成dump.rdb是根据CopyOnWrite的 之前也不是很懂为啥要有CopyOnWrite这个东西 翻看文章 ...
- 【Java】JavaMail使用网易企业邮箱发邮件
邮件发送器 /** * 邮件发送器 * * @author Zebe */ public class MailSender implements Runnable { /** * 收件人 */ pri ...
- 【CF1252F】Regular Forestation(重心,树同构)
题意:给定一棵n个点的树,问删去某个点之后所有的树同构,这样分割出来的树最多能有几棵 n<=4000 思路:分割成至少两个size相等的联通块之后size必定小于n/2,与树的重心的定义相同 预 ...
- 获取浏览区变化的方法resize() 方法
当调整浏览器窗口的大小时,发生 resize 事件. resize() 方法触发 resize 事件,或规定当发生 resize 事件时运行的函数. <html> <head> ...
- mktime夏令时处理
https://www.cnblogs.com/dongzhiquan/archive/2011/11/05/2237075.html 我们的最终目的是把字符串格式的时间转换为内部使用的“日历时间”, ...