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;
}

 

posted @ 2016-08-27 21:03  一入OI深似海  阅读(380)  评论(3编辑  收藏  举报