Gold Balanced Lineup(哈希表)

时间:2021-03-22 05:16:46
Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 10711   Accepted: 3182

Description

Farmer John's N cows (1 ≤ N ≤ 100,000) share many similarities. In fact, FJ has been able to narrow down the list of features shared by his cows to a list of only K different features (1 ≤ K ≤ 30). For example, cows exhibiting feature #1 might have spots, cows exhibiting feature #2 might prefer C to Pascal, and so on.

FJ has even devised a concise way to describe each cow in terms of its "feature ID", a single K-bit integer whose binary representation tells us the set of features exhibited by the cow. As an example, suppose a cow has feature ID = 13. Since 13 written in binary is 1101, this means our cow exhibits features 1, 3, and 4 (reading right to left), but not feature 2. More generally, we find a 1 in the 2^(i-1) place if a cow exhibits feature i.

Always the sensitive fellow, FJ lined up cows 1..N in a long row and noticed that certain ranges of cows are somewhat "balanced" in terms of the features the exhibit. A contiguous range of cows i..j is balanced if each of the K possible features is exhibited by the same number of cows in the range. FJ is curious as to the size of the largest balanced range of cows. See if you can determine it.

Input

Line 1: Two space-separated integers, N and K
Lines 2..N+1: Line i+1 contains a single K-bit integer specifying the features present in cow i. The least-significant bit of this integer is 1 if the cow exhibits feature #1, and the most-significant bit is 1 if the cow exhibits feature #K.

Output

Line 1: A single integer giving the size of the largest contiguous balanced group of cows.

Sample Input

7 3
7
6
7
2
1
4
2

Sample Output

4

题意:有n个二进制长度为k的特征数(十进制),求最大的连续的牛的数目,使这些牛每个特征的总数相等;

思路:

先把7个十进制特征数转换为二进制,并逆序存放到特征数组feature[ ][ ],得到:

7 à 1 1 1

6 à 0 1 1

7 à 1 1 1

2 à 0 1 0

1 à 1 0 0

4 à 0 0 1

2 à 0 1 0

(行数为cow编号,自上而下从1开始;列数为特征编号,自左到右从0开始)

再求sum数组,逐行累加得,sum数组为

1 1 1

1 2 2

2 3 3

2 4 3

3 4 3

3 4 4

3 5 4

再利用C[i][y]=sum[i][y]-sum[i][0]求C数组,即所有列都减去第一列

注意C数组有第0行,为全0

0 0 0 à 第0行

0 0 0

0 1 1

0 1 1

0 2 1

0 1 0

0 1 1

0 2 1

显然第2行与第6行相等,均为011,且距离最远,距离为6-2=4,这就是所求。

但是最大数据有10W个,即10W行,因此不能直接枚举找最大距离,必须用Hash查找相同行,找到相同行再比较最大距离。

注意C数组的值可能为负数,因此生成key值时要注意保证key为非负数。

 #include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std; const int prime = ;
struct node
{
int id;
struct node *next;
}*hash[prime];//邻接表 int sum[][];//从第一头牛到第i头牛,特征j总共出现了sum[i][j]次;
int c[][];//c[i][j] = sum[i][j] - sum[i][0];
int n,k,maxlen; bool check(int x, int y)
{
int i;
for(i = ; i < k; i++)
if(c[x][i] != c[y][i])
return false;
return true;
} void Hash(int ci)//ci代表序列的下标
{
int key = ,i;
//生成关键字
for(i = ; i < k; i++)
key += c[ci][i]*i;//key有可能是负值,要取绝对值,对大素数取余;
key = abs(key)%prime;
if(!hash[key])//出现新的key;
{
hash[key] = new struct node;
hash[key]->id = ci;
hash[key]->next = NULL;
}
//当key发生冲突时
else
{
struct node *p = hash[key];
if(check(p->id,ci))
{
int dis = ci-(p->id);
if(dis > maxlen)
maxlen = dis;//因p->id是从小到大的,所以当遍历有p->id满足时肯定是当前最优的,
return; //可以return; }
else
{
while(p->next)
{
if(check(p->next->id,ci))
{
int dis = ci-(p->next->id);
if(dis > maxlen)
maxlen = dis;
return; }
p = p->next;
}
//当ci序列与其它序列都不相同时就插到该链的最后;
struct node *tmp = new struct node;
tmp->id = ci;
tmp->next = NULL;
p->next = tmp;
}
}
return;
}
int main()
{
int i,j;
while(~scanf("%d %d",&n,&k))
{
for(i = ; i < k; i++)
{
sum[][i] = ;
c[][i] = ;//第0头牛初始化
}
memset(hash,,sizeof(hash));
Hash();//把第0头牛放入哈希表
maxlen = ;
for( i = ; i <= n; i++)
{
int x;
scanf("%d",&x);
for(j = ; j < k; j++)
{
sum[i][j] = sum[i-][j] + x%;
c[i][j] = sum[i][j]-sum[i][];
x = x/;
}
Hash(i);
}
printf("%d\n",maxlen);
}
return ;
}