题目大意:
给你一个长度为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题——单哈希+模拟
猜你喜欢
转载自blog.csdn.net/qq_43472263/article/details/104494327
今日推荐
周排行