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
*/

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章