排排站

【题目描述】

N头奶牛有一些共同之处(1 <= N <= 100000)。我们可以将这N头奶牛通过K种特征来归类(1 <= K <= 30)。

我们有一种简明的描述特征的方法——“特征码”,用一个长度为k的二进制串来表示这头牛的特征表现。例如,一头牛的“特征码”为13,转换为二进制就是1101,代表这头牛具有特征1、3、4(从右读到左),但是不表现特征2。总之,如果这头奶牛表现特征i,那么我们在他的“特征码”的二进制的第i位就为1。

现将奶牛排成了一个1~N的队列,他注意到一种确定的排列方法可以使奶牛们的表现更“平衡”。一个连续的[i,j]的范围平衡表示为K种特征都有同样多的奶牛。询问究竟可以排出一个多长的“平衡”队列。

【输入描述】

第一行两个整数n、k;

接下来n行,每行一个整数。

【输出描述】

输出一个整数表示最大的长度。

源代码:

#include<cstdio>
#include<cstring>
#define INF 999997
int n,m,ans,i[100001],S[100001][35],C[100001][35],Has[1000001];
int Get_Hash(int T)
{
    int t(0);
    for (int a=0;a<m;a++)
      t=t%INF+C[T][a]<<2;
    if (t<0)
      t=-t;
    return t%INF;
}
int main()
{
    scanf("%d%d",&n,&m);
    for (int a=1;a<=n;a++)
      scanf("%d",&i[a]);
    for (int a=1;a<=n;a++)
      for (int b=0;b<m;b++)
        if ((1<<b)&i[a])
          S[a][b]=S[a-1][b]+1;
        else
          S[a][b]=S[a-1][b];
    for (int a=1;a<=n;a++)
      for (int b=0;b<m;b++)
        C[a][b]=S[a][b]-S[a][0];
    memset(Has,-1,sizeof(Has));
    Has[0]=0;
    for (int a=1;a<=n;a++)
    {
        int t=Get_Hash(a);
        while (Has[t]!=-1)
        {
            bool Flag(0);
            for (int b=0;b<m;b++)
              if (C[Has[t]][b]!=C[a][b])
              {
                Flag=true;
                break;
              }
            if (!Flag&&a-Has[t]>ans)
            {
                ans=a-Has[t];
                break;
            }
            t++;
        }
        if (Has[t]==-1)
          Has[t]=a;
    }
    printf("%d",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/Ackermann/p/5815862.html