大概意思就是:
数组sum[i][j]表示从第1到第i头cow属性j的出现次数。
所以题目要求等价为:
求满足
sum[i][0]-sum[j][0]=sum[i][1]-sum[j][1]=.....=sum[i][k-1]-sum[j][k-1] (j<i)
中最大的i-j
将上式变换可得到
sum[i][1]-sum[i][0] = sum[j][1]-sum[j][0]
sum[i][2]-sum[i][0] = sum[j][2]-sum[j][0]
.....
sum[i][k-1]-sum[i][0] = sum[j][k-1]-sum[j][0]
令C[i][y]=sum[i][y]-sum[i][0] (0<y<k)
初始条件C[0][0~k-1]=0
所以只需求满足C[i][]==C[j][] 中最大的i-j,其中0<=j<i<=n。
C[i][]==C[j][] 即二维数组C[][]第i行与第j行对应列的值相等,
那么原题就转化为求C数组中 相等且相隔最远的两行的距离i-j。
以样例为例
7 37672142 先把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 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为非负数。
int N, K;
#define MAX 100005
#define MOD 99991
int maxlen;
int c[MAX][30];
int sum[MAX][30];
int feature[MAX][30];
struct HASH
{
int index;
struct HASH * next;
HASH() { next = NULL; }
} * hash[MOD];
bool cmp(int a, int b)
{
int i;
for (i = 0; i < K; ++i)
if (c[a][i] != c[b][i])
return false;
return true;
}
void Hash(int index)
{
int key = 0;
int i, j;
for (i = 0; i < K; ++i) {
key += c[index][i] * i;
}
key = MY_ABS(key) % MOD;
if (!hash[key]) {
HASH * tmp = new HASH;
tmp->index = index;
hash[key] = tmp;
} else {
HASH * tmp = hash[key];
if (cmp(tmp->index, index)) {
int d = index - tmp->index;
maxlen = MY_MAX(maxlen, d);
return ;
} else {
while (tmp->next) {
if (cmp(tmp->next->index, index)) {
int d = index - tmp->next->index;
maxlen = MY_MAX(maxlen, d);
return ;
}
tmp = tmp->next;
}
HASH * t = new HASH;
t->index = index;
tmp->next = t;
}
}
}
int main()
{
int i, j, k;
while (scanf("%d%d", &N, &K) == 2) {
for (i = 0; i < K; ++i) {//初始化第0头牛
c[0][i] = 0;
sum[0][i] = 0;
}
memset(hash, 0, sizeof(hash));
maxlen = 0;
Hash(0);
for (i = 1; i <= N; ++i) {
scanf("%d", &k);
for (j = 0; j < K; ++j) {
feature[i][j] = k % 2;
k /= 2;
sum[i][j] = sum[i - 1][j] + feature[i][j];
c[i][j] = sum[i][j] - sum[i][0];
}
Hash(i);
}
printf("%d\n", maxlen);
}
return 0;
}