2019牛客暑期多校训练营(第三场)J LRU management

模拟链表,加上map查询链表中是否有某元素。

快读快写等优化,时间200ms。

#include <bits/stdc++.h>
using namespace std;
char ssssss[30];
inline int read()
{
    int x=0,f=1; char ch=getchar();
    while (ch<'0'||ch>'9') {if (ch=='-') f=-f; ch=getchar();}
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x*f;
}
inline void writeln(int x)
{
	if (x<0) putchar('-'),x=-x; 
	if (!x) putchar('0'); else 
	{
	    int len=0;  
	    while (x) ssssss[++len]=x%10+'0',x/=10;
	  	while (len) putchar(ssssss[len--]);
	} 
	putchar('\n');
}
typedef long long ll;
typedef long double ld;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<ld,ld> pdd;
#define F first
#define S second
const int N = 5e5 + 10;
const ll INF64=8000000000000000000LL;
const int INF=0x3f3f3f3f;
const ll MOD=ll(1e9+7);
const ld PI=acos(-1);
const ld eps=1e-9;
using namespace std;
int nidx,M,size;
int val[N];
ll cpu[N];
int pre[N],nxt[N];
unordered_map<ll,int>mp;
unordered_map<ll,int>::iterator it;
inline void remove(int idx)
{
    if(idx==nidx)//如果删除的是链表最后一个元素
    {
        nxt[pre[idx]]=nxt[idx];//=0好像也行
        nidx=pre[idx];
    }
    else
    {
        nxt[pre[idx]]=nxt[idx];
        pre[nxt[idx]]=pre[idx];
    }
    pre[idx]=nxt[idx]=val[idx]=cpu[idx]=0;
    --size;//链表总元素-1
}
inline void add(int v,ll now)//从链表末尾加入元素
{
//  puts("ok3");
    nxt[nidx]=nidx+1;
    pre[nidx+1]=nidx;
    val[nidx+1]=v;
    cpu[nidx+1]=now;
//  mp[now]=nidx+1;
    ++nidx;
    ++size;
    if(size>M)
    {
    //  puts("ok4");
    //  cout<<nxt[0]<<"--"<<cpu[nxt[0]]<<endl;
        mp.erase(cpu[nxt[0]]);//也可以写在remove函数里 ,
        remove(nxt[0]);//必须先erase,再remove 可以想想为什么
         
    }
//  puts("ok2");
}
char s[20];
ll get(){
    int le = strlen(s);
    ll ans = 0;
    for(int i = 0;i < le;++i){
        ans = ans * 27 + s[i] - 'a' + 1;
    }
    return ans;
}
 
int main()
{
    /*ios::sync_with_stdio(false);
    cin.tie(0);*/
    int t,Q,opt,v;
    t=read();
    //scanf("%d",&t);
    while(t--)
    {
        mp.clear();
        nidx=size=0;
        Q=read(),M=read();
        //scanf("%d%d",&Q,&M);
        for(int i=1;i<=Q;i++)
        {
            opt=read();
            scanf("%s",s);
            v=read();
            //scanf("%d%s%d",&opt,s,&v);
            ll now=get();
            it = mp.find(now);
            if(opt==0)
            {
                //puts("ok1");
                if(it != mp.end())
                {
                    int pos=it->second;//找的对应位置
                    int pr=val[pos];
                    remove(pos);
                    add(pr,now);
                    writeln(pr);
                    //printf("%d\n",pr);
                    it->second=nidx;
                }
                else
                {
                    add(v,now);
                    writeln(v);
                //    printf("%d\n",v);
                    mp[now] = nidx;
                }
            }
            else
            {
                //cout<<mp[now]<<"---"<<now<<endl;
                if(it == mp.end())
                puts("Invalid");
                else
                {
                //  puts("ok");
                    int pos=it->second;
                    if(v==1)pos=nxt[pos];//后继
                    else if(v==-1)pos=pre[pos];//前驱
                    else pos=pos;
                    if(pos)
                    {
                    	writeln(val[pos]);
                        //printf("%d\n",val[pos]);
                    }
                    else
                    puts("Invalid");//不存在
                }
            }
        }
        memset(val,0,sizeof(int) * (nidx + 10));
        memset(pre,0,sizeof(int) * (nidx + 10));
        memset(nxt,0,sizeof(int) * (nidx + 10));
        memset(cpu,0,sizeof(int) * (nidx + 10));
     }
    return 0;
}
 
/*
1
8 3
0 0101010 1
0 0101011 2
1 0101010 1
0 1100000 3
0 0101011 -1
0 1111111 4
1 0101011 -1
1 0101010 0
*/

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值