題目大意:
給你一個長度爲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 */
CCPC2019哈爾濱站L題——單哈希+模擬
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.