(Nowcoder) J LRU management (静态链表)

本文分享了一种使用链表和哈希桶解决大模拟问题的方法,通过合理设置哈希桶大小并利用链表指针进行节点操作,有效降低了复杂度,实现了对大量数据的高效处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

传送门

题意读懂了,感觉这就是个大模拟,但是直接模拟复杂度太大,所以我们要用链表指针搞一搞。不知道是不是我写的实在太挫,还是卡常,一直狂T,哭了。

划重点,加上这个才过。设置哈希桶大小,队友加了才过,估了,才知道这玩也,相见恨晚,还是太菜了呀。

rk.rehash(500005);
a.rehash(500005);

#include<bits/stdc++.h>
#define il inline
#define pb push_back
#define ms(_data,v) memset(_data,v,sizeof(_data))
#define sc(n) scanf("%d",&n)
#define SC(n,m) scanf("%d %d",&n,&m)
#define SZ(a) int((a).size())
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define drep(i,a,b) for(int i=a;i>=b;--i)
using namespace std;
typedef long long ll;
const ll inf=0x3f3f3f3f;
const double pi=acos(-1.0);
const double eps=1e-9;
const int maxn=1e6+5;
int T,q,m;
struct node{
    int pre,nxt;
    int val;
};
unordered_map<int,node> a;
unordered_map<string,int> rk;
char alls[maxn][20];
int allop[maxn],allv[maxn];
inline int read(){
    char ch = getchar(); int x = 0, f = 1;
    while(ch < '0' || ch > '9') {
        if(ch == '-') f = -1;
        ch = getchar();
    } while('0' <= ch && ch <= '9') {
        x = x * 10 + ch - '0';
        ch = getchar();
    } return x * f;
}
int main(){
    T = read();
    rk.rehash(500005);
    a.rehash(500005);
    while(T--){
        q = read();
        m = read();
        int op,s,v,nlen=0;
        int fa=-1,last;
        a.clear(),rk.clear();
        rep(i,1,q){
            allop[i] = read();
            scanf(" %s",alls[i]);
            allv[i] = read();
        }
        int cnt=0;
        rep(i,1,q){
            if(rk.count(alls[i])==0) rk[alls[i]]=++cnt;
        }
        rep(i,1,q){
            op=allop[i],s=rk[alls[i]],v=allv[i];
            if(op==0){ //add
                if(nlen==0){
                    a[fa].nxt=s;
                    a[s].pre=fa,a[s].val=v;
                    last=s,nlen++;
                    printf("%d\n",v);
                }
                else{
                    if(a.count(s)==0 || a[s].val==inf){ //不存在s
                        a[last].nxt=s,a[s].pre=last;
                        a[s].val=v,last=s,nlen++;
                        printf("%d\n",v);
                        if(nlen>m){ //删除头部
                            if(m==1){
                                int fato=a[fa].nxt;
                                a[fato].val=inf;
                                a[fato].pre=0,a[fato].nxt=0;
                                a[fa].nxt=s,a[s].pre=fa;
                                last=s;
                            }
                            else{
                                int fato=a[fa].nxt;
                                a[fato].val=inf;
                                int to=a[fato].nxt;
                                a[to].pre=fa,a[fa].nxt=to;
                                a[fato].pre=0,a[fato].nxt=0;
                            }
                            nlen--;
                        }
                    }
                    else{//存在s
                        printf("%d\n",a[s].val);
                        if(s==last) continue;
                        int spre=a[s].pre,sto=a[s].nxt;
                        a[sto].pre=spre,a[spre].nxt=sto;
                        a[last].nxt=s;
                        a[s].pre=last;
                        last=s;
                    }
                }
            }
            else{ //query
                if(a.count(s)==0 || a[s].val==inf){
                    puts("Invalid");
                }
                else{
                    if(v==0)    printf("%d\n",a[s].val);
                    if(v==-1){
                        if(a[s].pre==fa)    puts("Invalid");
                        else    printf("%d\n",a[a[s].pre].val);
                    }
                    if(v==1){
                        if(s==last) puts("Invalid");
                        else printf("%d\n",a[a[s].nxt].val);
                    }
                }
            }
        }
              
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值