zoukankan      html  css  js  c++  java
  • 2019CCPC哈尔滨 L LRU Algorithm(字符串hash)

    题意:

    题目背景:cache的LRU算法。给定一串长度为n的cache访问序列,多个询问q,每次给mi,表示cache的容量为mi,然后mi个数的序列,问是否存在cache表为这个序列的情况。

    题目有多组输入。n<=5000,q<=5000, (sum n<=20000,sum q<=20000,sum mi<=1e6)

    思路:

    按照LRU算法的规律可以很容易发现,对于第i次访问,cache表中的数就是从访问序列第i位往前推,每次未出现的数就加入cache表下一位即可,而cache表的容量大小只是将得到的序列进行截断而已,因此可以预处理出所有位向前推到第1位(假设最多数字种类数为len),1-len所有容量大小所对应的字符串哈希值,时间复杂度为(O(n^2))

    每次查询,首先将末尾的0去掉,如果剩余长度l为0,则直接输出yes,否则遍历1-n所有位长度为l的哈希值,若相同则输出Yes(可以再O(N)扫一边确认是否真的相同),若均不相同则输出NO

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    typedef unsigned long long ull;
    typedef long long ll;
    const int maxn=5e3+5;
    int seed=13331;
    ull has[maxn][maxn];
    int a[maxn];
    int x[maxn];
    int vis[maxn];
    void init(int n){
        memset(vis,0,sizeof(int)*(n+1));
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++)has[i][j]=0;
        }
    }
    int main () {
        int T;
        scanf("%d",&T);
        while(T--){
            int n,q;
            scanf("%d%d",&n,&q);
            for(int i=1;i<=n;i++){
                scanf("%d",&a[i]);
            }
            init(n);
            for(int i=1;i<=n;i++){
                int cnt=0;
                for(int j=i;j>=1;j--){
                    if(vis[a[j]]!=i){
                        cnt++;
                        has[i][cnt]=has[i][cnt-1]*seed+a[j];
                        vis[a[j]]=i;
                    }
                }
            }
            while(q--){
                int mi;
                scanf("%d",&mi);
                for(int i=1;i<=mi;i++){
                    scanf("%d",&x[i]);
                }
                while(x[mi]==0)mi--;
                if(mi==0){
                    puts("Yes");
                    continue;
                }
                ull hasx=0;
                for(int i=1;i<=mi;i++){
                    hasx=hasx*seed+x[i];
                }
                int flag=0;
                for(int i=1;i<=n;i++){
                    if(has[i][mi]==hasx){
                        memset(vis,0,sizeof(int)*(n+1));
                        int ok=1;
                        int cnt=0;
                        for(int j=i;j>=1 && cnt<mi;j--){
                            if(!vis[a[j]]){
                                if(a[j]!=x[++cnt]){
                                    ok=0;
                                    break;
                                }
                                vis[a[j]]=1;
                            }
                        }
                        if(ok){
                            puts("Yes");
                            flag=1;
                            break;
                        }
                    }
                }
                if(!flag){
                    puts("No");
                }
            }
        }
    }
    
  • 相关阅读:
    android 振动
    linux实用命令-查看文件夹的大小
    无显示屏的开发板抓屏
    传感器Sensor的使用-距离感应(听筒模式)
    4.4原生应用获取通话状态
    git服务器的使用
    (转)浅谈ANR及log分析ANR
    ubuntu下从软件中心安装软件时的软件缓存目录
    mysql————Innodb的可重复读的情况下如何避免幻读?
    MyISAM和Innodb的区别
  • 原文地址:https://www.cnblogs.com/ucprer/p/13766858.html
Copyright © 2011-2022 走看看