2019牛客网多校第三场J-LRU management

题目

要求实现一个双向循环链表,要求实现按照序号访问,并能增删查改。

题解

这也是我一直想写的东西,在赛后看题解时发现比较好的代码。
用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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

总想玩世不恭

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值