Gold Balanced Lineup--POJ 3274

1、题目类型:哈希表、位运算。

2、解题思路:题意,N个数,它们用K位的二进制表示,寻找最长的区间使其各个进制位上的和都没有发生变化的情况。步骤,(1)将所有N个数转化为K位的二进制形式,并比较与初始位置的差值存储在arr[i]中;(2)Hash编码arr[i],Hash编码公式为:tmp=((tmp<<2)+(v[i]>>4))^(v[i]<<10) ;(3)判断是否存在冲突,存在冲突并且匹配成功时,判断区间大小,直到找到答案。

3、注意事项:注意当Hash编码冲突且匹配不成功时,tmp++,下一位保存;注意取prime的大小要求适当。

4、实现方法: 

  
    
1 #include < iostream >
2   using namespace std;
3   #define maxn 100010
4 #define prime 999983
5
6 int n,k,ans;
7 int arr[maxn][ 31 ],sum[maxn][ 31 ],hash[ 1000000 ];
8
9 // Hash编码方式
10 int Encode( int * v, int k)
11 {
12 int i,tmp = 0 ;
13 // Hash公式
14 for (i = 0 ;i < k;i ++ )
15 tmp = ((tmp << 2 ) + (v[i] >> 4 )) ^ (v[i] << 10 );
16 tmp = tmp % prime;
17 if (tmp < 0 ) tmp = tmp + prime;
18 return tmp;
19 }
20
21 int main()
22 {
23 int i,j,num,tmp;
24 memset(sum, 0 , sizeof (sum));
25 memset(hash, - 1 , sizeof (hash));
26 memset(arr, 0 , sizeof (arr));
27
28 scanf( " %d%d " , & n, & k);
29 hash[Encode(arr[ 0 ],k)] = 0 ;
30
31 for (i = 1 ;i <= n;i ++ )
32 {
33 scanf( " %d " , & num);
34 for (j = 0 ;j < k;j ++ )
35 {
36 arr[i][j] = num % 2 ;
37 num >>= 1 ;
38 sum[i][j] = sum[i - 1 ][j] + arr[i][j];
39 arr[i][j] = sum[i][j] - sum[i][ 0 ];
40 }
41 tmp = Encode(arr[i],k);
42 // Hash存在冲突
43 while (hash[tmp] !=- 1 )
44 {
45 // 验证arr[i]是否相同
46 for (j = 1 ;j < k;j ++ )
47 {
48 if (arr[i][j] != arr[hash[tmp]][j])
49 break ;
50 }
51 if (j == k)
52 {
53 if (i - hash[tmp] > ans)
54 ans = i - hash[tmp];
55 break ;
56 }
57 tmp ++ ;
58 }
59 // Hash不存在冲突
60 if (hash[tmp] ==- 1 )
61 hash[tmp] = i;
62 }
63 printf( " %d\n " ,ans);
64 return 0 ;
65 }

 

 

 

你可能感兴趣的:(poj)