首先发出题目链接:
链接:https://ac.nowcoder.com/acm/contest/883/J
来源:牛客网
涉及:unordered_map,链表
点击这里回到2019牛客暑期多校训练营解题—目录贴
题目如下:
此题目题解用字典树,但是用STL也可以稳过。考的是基本的增删改查。
为了让增删和改更加快速,可以使用链表来实现,使得增删和改的复杂度为O(1),链表中存对应的数字字符串和值。
但是链表用于查找的话复杂度是 O(n),所以还需使用hash表来进行查找需要改链表的哪个位置,hash表可以用STL自带的unordered_map来实现。
用unordered_map,键值则是需要查找的数字字符串,实值则是指向链表中需要修改位置的迭代器。注意如果删除链表内的元素时,还要同时删除map中链表迭代器位置得到字符串。
最后还要注意一下输入输出最好用scanf和printf,如果你要用cin输入,请在代码前加上
ios::sync_with_stdio(false);
cin.tie(0);
要用cout输出的话,请把endl宏定义为’\n’
#define endl "\n"
代码如下:
#include <iostream>
#include <string>
#include <unordered_map>
#include <list>
using namespace std;
typedef long long ll;
typedef pair<string, int> P;//链表中所存的数据类型
list<P> table;//链表
unordered_map<string, list<P>::iterator> mp;//hash表
int t, q, m, opt, v;//题目所给变量
char s[20];//字符串,由于不用cin输入,所以用字符数组
int main(){
scanf("%d", &t);
while(t--){
scanf("%d%d", &q, &m);
mp.clear();//清空mp
table.clear();//清空table
while(q--){
scanf("%d%s%d", &opt, s, &v);//输入命令
if(opt == 0){
if(mp.find(s) != mp.end()){//查找链表中是否存在这个元素
printf("%d\n", mp[s]->second);//找到了输出对于值
table.push_back(*mp[s]);//下面是把这一元素移到末尾的操作
table.erase(mp[s]);
mp[s] = --table.end();
}
else{
printf("%d\n", v);//找不到就输出命令所给的值
table.push_back(P(s, v));//下面是把这一元素放到链表内操作
if(table.size() > m){//判断链表内元素是否超过限制
mp.erase(table.front().first);
table.pop_front();
}
mp[s] = --table.end();
}
}
else{
if(mp.find(s) == mp.end()) printf("Invalid\n");//在链表内找不到该元素
else{
auto it = mp[s];//找到该元素
if(v == 1 && (*it) == table.back()) printf("Invalid\n");//判断元素是否合法
else if(v == -1 && (*it) == table.front()) printf("Invalid\n");//判断元素是否合法
else{//元素合法并输出值
if(v == 1) ++it;
if(v == -1) --it;
printf("%d\n", it->second);
}
}
}
}
}
return 0;
}