题目
要求实现一个双向循环链表,要求实现按照序号访问,并能增删查改。
题解
这也是我一直想写的东西,在赛后看题解时发现比较好的代码。
用map+list实现,而我自己也用结构体+map模拟实现了一个,坑比较多。
比如输出Invalid开头要大写
以及用unordered_map代替map来加速。
代码1 (map+list)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 200005;
template <class T>
void read(T &x) {
T f=1;x=0;char s=getchar();
while(s<'0'||s>'9') {if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9') {x=x*10+s-'0';s=getchar();}
x *= f;
}
struct node{
string s;
int v;
node(string s_,int v_):v(v_){s=s_;}
};
list<node> L;
unordered_map<string,list<node>::iterator> mp;
int t,m,q;
char s[15];
int main() {
read(t);
while(t--) {
mp.clear(); L.clear();
read(q), read(m);
for(int i=0,opt,v;i<q;i++) {
scanf("%d%s%d",&opt,s,&v);
if(!opt) {
if(mp.find(s)!=mp.end()) {
auto it = mp[s];
int temp = it->v;
printf("%d\n",temp);
L.erase(it);
L.push_back(node(s,temp));
mp[s] = prev(L.end());
} else {
L.push_back(node(s,v));
mp[s] = prev(L.end());
printf("%d\n",v);
if(L.size()>m) {
string temp = L.front().s;
L.pop_front();
mp.erase(temp);
}
}
} else {
if(mp.find(s)==mp.end()) {puts("Invalid");continue;}
auto it = mp[s];
switch (v)
{
case 1:
if(next(it)==L.end()) puts("Invalid");
else printf("%d\n",next(it)->v);
break;
case 0:
printf("%d\n",it->v);
break;
default:
if(it==L.begin()) puts("Invalid");
else printf("%d\n",prev(it)->v);
break;
}
}
}
}
return 0;
}
代码2 (结构体+map)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 500005;
template <class T>
void read(T &x) {
T f=1;x=0;char s=getchar();
while(s<'0'||s>'9') {if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9') {x=x*10+s-'0';s=getchar();}
x *= f;
}
int t;
int q,n,m;
struct node{
int id,pre,nxt,v;
string s;
}e[maxn];
int main() {
read(t);
while(t--) {
unordered_map<string,int> mp;
mp.clear();
read(q); read(m);
int fst = 1, lst=0;
int cnt = 0;
for(int i=0;i<q;i++) {
int opt,v;
char s[15];
scanf("%d%s%d",&opt,s,&v);
if(!opt) {
if(!mp[s]) {
cnt++;
mp[s] = ++lst;
e[lst].pre = lst-1;
e[lst-1].nxt = lst;
e[lst].nxt = 0;
e[lst].v = v;
e[lst].s = s;
if(cnt>m) {
mp[e[fst].s] = 0;
fst=e[fst].nxt;
e[fst].pre = 0;
cnt--;
}
printf("%d\n",v);
} else {
int id = mp[s];
printf("%d\n",e[id].v);
if(id==fst && id!=lst) { //坑点1:只有一个元素时既是开头也是结尾
fst = e[fst].nxt;
e[fst].pre = 0;
mp[s] = ++lst;
e[lst].v = e[id].v;
e[lst].s = s;
e[lst].pre = lst-1;
e[lst].nxt = 0;
e[lst-1].nxt = lst;
}
else if(id!=lst) {
e[e[id].pre].nxt = e[id].nxt;
e[e[id].nxt].pre = e[id].pre;
mp[s] = ++lst;
e[lst].v = e[id].v;
e[lst].s = s;
e[lst].pre = lst-1;
e[lst].nxt = 0;
e[lst-1].nxt = lst;
}
}
}else{
if(!mp[s]) {
puts("Invalid");
} else {
int id = mp[s];
if(v==-1) {
int idx = e[id].pre;
if(id==fst) puts("Invalid"); //坑点2:原本写的if(idx==0),但是在构建的时候可能会出现错误(至今未找到)
else printf("%d\n",e[idx].v);
}else if(v==0) {
printf("%d\n",e[id].v);
}else {
int idx = e[id].nxt;
if(id==lst) puts("Invalid");
else printf("%d\n",e[idx].v);
}
}
}
}
}
return 0;
}