The 2019 China Collegiate Programming Contest Harbin Site L.LRU Algorithm(哈希+LRU算法)

题目

T组样例,每次给出一个n,一个q,

表示对长度为n序列a[](1<=ai<=n)做LRU替换算法,

q次询问,第i次给出一个缓存容量mi,和mi个整数,

表示缓存区当前是什么样子的,空位用0表示,

第i次询问,是否在对长度为mi的缓存区,进行1到n的LRU替换算法时,

存在某一时刻,使得缓存区的状态和给定的状态相等,

存在输出Yes,否则输出No

保证所有n之和不超过2e4,所有q之和不超过2e4,所有m之和不超过2e6,时限1秒

思路来源

https://www.cnblogs.com/clrs97/p/11793253.html Claris博客

题解

核心思路是,缓存区的长度,只能决定在不够长的时候,被踢出的值是哪些,

而留在缓存区里的那m个,一定是缓存区无限情况下的一个长为m前缀

考虑按长度离线,每插入一个数,就重构长度分别为1,...,n的前缀的哈希值,

然后遍历q个询问,比较此刻长度为mi的前缀的哈希值是否与给定询问的哈希值相等,

注意哈希值全为0的情况,为了保险可采用双哈希

代码

#include<iostream>
#include<cstdio>
using namespace std;
typedef unsigned long long ull;
const int N=5e3+10,M=2e3+10;
int T,n,m,q,a[N],len[M];
ull f[N],g[M];
int now[N];
bool ans[M];
void add(int x){//把x拽到最前面去
    int i;
    for(i=1;i<=n;++i){
        if(now[i]==x)break;
    }
    for(;i<n;i++){
        now[i]=now[i+1];
    }
    for(int i=n;i>1;--i){
        now[i]=now[i-1];
    }
    now[1]=x;
}
void cal(int n){
    for(int i=1;i<=n;++i){
        f[i]=f[i-1]*23333+now[i]+233;
    }
}
int main(){
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&n,&q);
        for(int i=1;i<=n;++i){
            scanf("%d",&a[i]);
        }
        for(int j=1;j<=q;++j){
            scanf("%d",&m);
            for(int i=1;i<=m;++i){//0默认跟在最后
                scanf("%d",&now[i]);
            }
            cal(m);
            len[j]=m;
            g[j]=f[m];
            ans[j]=0;
        }
        for(int i=1;i<=n;++i){
            now[i]=0;
        }
        //每时每刻算一个前缀为m的哈希值
        for(int i=0;i<=n;++i){//注意全0的情况
            if(i){
                add(a[i]);
            }
            cal(n);
            for(int j=1;j<=q;++j){
                if(f[len[j]]==g[j]){
                    ans[j]=1;
                }
            }
        }
        for(int j=1;j<=q;++j){
            puts(ans[j]?"Yes":"No");
        }
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小衣同学

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

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

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

打赏作者

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

抵扣说明:

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

余额充值