CCPC2019哈尔滨站L题——单哈希+模拟

题目链接:https://codeforces.com/gym/102394/problem/L

题目大意:

给你一个长度为n的序列,即执行序列,然后给你qu次查询操作,每次给你一个m值,即内存大小,以及一个长度为m的序列状态,然后让你判断在执行LRU算法(在内存大小为m)时是否会出现该序列状态。

 题解:

比赛最后一个小时开的这个题,当时想着先暴力一下,之后再找个什么优化,结果暴力的比赛后也没写完,自闭。

首先我们可以发现只需要每一步都按照内存无限大只需LRU算法,而对应每一步的操作内存为m的序列,其实就是1-m的前缀序列,然后我们考虑怎么去快速的表示一个序列,以及实现快速查找,不难想到哈希一下(我怎么没想到)。

有关哈希的具体知识可以参考我的博客:https://blog.csdn.net/qq_43472263/article/details/99414049

我们给每一次操作后的序列的前缀进行单哈希操作,为了防止哈希冲突,我们在最后判断哈希相等后,还需要进行二次判断,这里可以用双哈希,或者再判断序列是否相等。

代码实现:

#pragma GCC optimize(2)
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<vector>
#include<map>
#include<set>
#include<stack>
#include<queue>
#define PI atan(1.0)*4
#define E 2.718281828
#define rp(i,s,t) for (register int i = (s); i <= (t); i++)
#define RP(i,t,s) for (register int i = (t); i >= (s); i--)
#define ll long long
#define ull unsigned long long
#define mst(a,b) memset(a,b,sizeof(a))
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
#define debug printf("ac\n");
using namespace std;
inline int read()
{
    int a=0,b=1;
    char c=getchar();
    while(c<'0'||c>'9')
    {
        if(c=='-')
            b=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9')
    {
        a=(a<<3)+(a<<1)+c-'0';
        c=getchar();
    }
    return a*b;
}
const int INF = 0x3f3f3f3f;
const int N = 5e3+7;
const ll mod =1e9+7;
const int p=998244353;
ll Hash[N][N],val;//存储前缀哈希值,即Hash[i][j]表示第i次操作后,1-j序列的哈希值
int q[N][N],t[N];//q[i][j]表示第i次操作后,第j个位置的数
int T,n,qu,m,top;
inline void init(){//初始化
    rp(i,0,n)
        rp(j,0,n)
            q[i][j]=Hash[i][j]=0;
    top=0;//记录序列的有效长度
}
int main(){
    T=read();
    while(T--){
        n=read(),qu=read();
        init();
        rp(i,1,n){
            rp(j,1,n) q[i][j]=q[i-1][j];//先把上一次操作的序列复制下来
            int x=read();
            int pos=0;
            rp(j,1,top){//看插入的数序列中是否已存在
                if(q[i][j]==x){
                    pos=j;
                    break;
                }
            }
            if(pos){//如果已存在,那么就把序列中它前面的所有数往后挪
                RP(j,pos,1) q[i][j]=q[i][j-1];
            }
            else{//不存在,把序列所有数往后挪
                RP(j,++top,1) q[i][j]=q[i][j-1];
            }
            q[i][1]=x;//最前面的位置留给插入的数
            rp(j,1,n) Hash[i][j]=(Hash[i][j-1]*p+q[i][j])%mod;//一次前缀的单哈希操作
        }
        // rp(i,0,n){
        //     rp(j,1,n) cout<<q[i][j]<<" ";
        //     cout<<endl;
        // }
        while(qu--){
            m=read();
            val=0;//val记录给定序列的哈希值
            rp(i,1,m){
                t[i]=read();
                val=(val*p+t[i])%mod;
            }
            int flag=0;
            rp(i,0,n){//枚举每一次操作,注意包含初始状态
                if(Hash[i][m]==val){//如果某一个操作后的1-m的哈希值等于给定序列的哈希值
                    int fg=1;
                    rp(j,1,m){//二次判断是否相等,防止哈希冲突
                        if(q[i][j]!=t[j]){
                            fg=0;
                            break;
                        }
                    } 
                    if(fg){
                        flag=1;
                        break;
                    }
                }
            }
            if(flag) puts("Yes");
            else puts("No");
        }
    }
    return 0;
}
/*
1 
7 5 
4 3 4 2 3 1 4 
1 4 
2 2 3 
3 3 2 1 
4 4 1 3 2 
4 3 4 0 0
*/
发布了342 篇原创文章 · 获赞 220 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_43472263/article/details/104494327