1247 排排站 USACO(查分+hash)
Posted 一入OI深似海
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了1247 排排站 USACO(查分+hash)相关的知识,希望对你有一定的参考价值。
/* 暴力查分 n*n */ #include<cstdio> #include<cstring> #include<iostream> #define maxn 100010 using namespace std; int n,m,a[maxn],ans,p[maxn][31],r[31]; int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if((1<<j-1)&a[i])p[i][j]=p[i-1][j]+1; else p[i][j]=p[i-1][j]; for(int i=1;i<=n;i++) for(int j=i+1;j<=n;j++) { int falg=0; for(int k=1;k<=m;k++) r[k]=p[j][k]-p[i-1][k]; for(int k=2;k<=m;k++) if(r[k]!=r[k-1]){falg=1;break;} if(!falg)ans=max(ans,j-i+1); } printf("%d\n",ans); return 0; }
/* 还是差分 因为对于符合条件的序列 有 sj0 - si0 = sj1 - si1 =...= sjk-1 - sik-1 也就是说 如果存在i j 满足 sj1 - sj0 == si1 - si0 sj2 - sj0 == si2 - si0 ...... sjk-1 - sj0 == sik-1 - si0 我们定义c[i,j]=s[i,j]-s[i,0] 问题就转化成了 找隔得最远的ij 满足c[i] 和 c[j] 一样 这里用hash加速查找 给每个c[i] 搞一个hash值 放到hash表里 */ #include<cstdio> #include<cstring> #include<iostream> #include<cstdlib> #define maxn 100010 #define mod 999997 using namespace std; int n,m,a[maxn],ans,p[maxn][35],c[maxn][35],has[maxn*10]; int Get_hash(int *a) { int r=0; for(int i=0;i<m;i++) r=r%mod+a[i]<<2; if(r<0)r=-r; return r%mod; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=1;i<=n;i++) for(int j=0;j<m;j++) if((1<<j)&a[i])p[i][j]=p[i-1][j]+1; else p[i][j]=p[i-1][j]; for(int i=1;i<=n;i++) for(int j=0;j<m;j++) c[i][j]=p[i][j]-p[i][0]; memset(has,-1,sizeof(has)); has[0]=0; for(int i=1;i<=n;i++) { int k=Get_hash(c[i]); while(has[k]!=-1) { int falg=0; for(int j=0;j<m;j++) if(c[has[k]][j]!=c[i][j]) { falg=1;break; } if(!falg&&i-has[k]>ans) { ans=i-has[k];break; } k++; } if(has[k]==-1)has[k]=i; } printf("%d\n",ans); return 0; }
以上是关于1247 排排站 USACO(查分+hash)的主要内容,如果未能解决你的问题,请参考以下文章
bzoj 1702: [Usaco2007 Mar]Gold Balanced Lineup 平衡的队列hash
bzoj1692: [Usaco2007 Dec]队列变换(hash+二分求LCP)
P1360 [USACO07MAR]Gold Balanced Lineup G(前缀和&Hash)
USACO 2015 December Contest Max Flow (bzoj4390)