POJ 3274 -- Gold Balanced Lineup
Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 16467 | Accepted: 4664 |
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
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
Sample Input
7 3
7
6
7
2
1
4
2
Sample Output
4
Hint
Source
解题思路:
牛的特征数组为f[N][K],sum[i][j]为第i头牛到第0头牛特征j出现的次数,
对于区间第i头牛到第j头牛,特征出现的次数都相同,对应如下等式
sum[j][0] - sum[i][0] = sum[j][1] - sum[i][1] = ... = sum[j][K] - sum[i][K]
我们要求满足上述等式的max(j - i)
经过变换,有:
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] - sum[i][0] = sum[j][K] - sum[j][0]
求满足上述等式组的max(j - i)
所以我们令c[i][j] = sum[i][j] - sum[i][0],上述等式组就变成了:
c[i][1] = c[j][1]
c[i][2] = c[j][2]
...
c[i][K] = c[j][K]
即为c[i][] = c[j][],求满足数组c[][]的第i行和第j行对应相等的max(j - i)
我们只要将特征数组经过上述转化,转化为求满足数组c[][]的第i行和第j行对应相等的max(j - i)
相应的使用hash表,先找到相同的两行,在寻找max(j - i)
1 #include<iostream> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 int f[100001][31];//记录牛的特征 6 int sum[100001][31]; 7 int c[100001][31]; 8 int ans; 9 int n,k; 10 11 const int mod = 100000; 12 13 class HashTable{ 14 public: 15 int pi;//用来存储数组c的行下标 16 HashTable *next; 17 HashTable() 18 { 19 next = 0; 20 } 21 }; 22 23 HashTable *Hash[mod]; 24 25 ///计算数组c第i行的key值 26 int computeKey(int i) 27 { 28 int key = 0; 29 for(int j=1;j<=k;j++) 30 { 31 key += c[i][j] * j; 32 } 33 key = abs(key)%mod;//由于c[][]有正有负,因此key值可能为负 34 return key; 35 } 36 37 bool compare(int i,int j) 38 { 39 for(int m=1;m<=k;m++) 40 { 41 if(c[i][m] != c[j][m]) 42 return false; 43 } 44 return true; 45 } 46 47 void Insert(int i) 48 { 49 int key = computeKey(i); 50 if(!Hash[key])//没有发生冲突 51 { 52 HashTable *temp = new HashTable; 53 temp->pi = i; 54 Hash[key] = temp; 55 } 56 else{//发生冲突 57 HashTable *temp = Hash[key]; 58 ///c数组的两行相等,计算j-i的值,如果比当前值ans大,就更新ans 59 if(compare(temp->pi,i)) 60 { 61 if((i - temp->pi) > ans) 62 ans = i-temp->pi; 63 ///i一定大于temp->pi 64 ///如果又有一行j等于行temp->pi,那么j-temp->pi 65 ///一定小于j - i,所以不需要存i 66 return; 67 }else{ 68 while(temp->next) 69 { 70 temp = temp->next; 71 if(compare(temp->pi,i)) 72 { 73 if((i - temp->pi) > ans) 74 ans = i - temp->pi; 75 return; 76 } 77 } 78 79 ///发生地址冲突,而且没有与第i行相同的行 80 temp->next = new HashTable; 81 temp->next->pi = i; 82 } 83 } 84 return; 85 } 86 87 int main() 88 { 89 90 while(cin>>n>>k) 91 { 92 memset(Hash,0,sizeof(Hash)); 93 94 for(int p=1;p<=k;p++) 95 { 96 c[0][p]=0; //第0只牛的特征默认为全0 97 sum[0][p]=0; 98 } 99 Insert(0); //把第0只牛先放入哈希表 100 memset(f,0,sizeof(f)); 101 ///输入特征数组feature[][] 102 for(int i=1;i<=n;i++) 103 { 104 int j = 1; 105 int feature = 0; 106 cin>>feature; 107 while(feature) 108 { 109 f[i][j++] = feature%2; 110 feature = feature/2; 111 } 112 } 113 ///计算sum[][] 114 for(int i=1;i<=k;i++) 115 sum[1][i] = f[1][i]; 116 for(int i=2;i<=n;i++) 117 { 118 for(int j=1;j<=k;j++) 119 sum[i][j] =sum[i-1][j]+f[i][j]; 120 } 121 ///计算c[][] 122 for(int i=0;i<=n;i++) 123 c[i][1] = 0; 124 for(int j=2;j<=k;j++)//列 125 { 126 for(int i=1;i<=n;i++) 127 c[i][j] = sum[i][j] - sum[i][1]; 128 } 129 ///将c的所有行存入hash表 130 ans = 0; 131 for(int i=1;i<=n;i++) 132 Insert(i); 133 134 cout<<ans<<endl; 135 } 136 return 0; 137 }
测试样例: 7 3 7 6 7 2 1 4 2 7 3 7 7 7 7 7 7 7 4 4 1 2 4 8 4 4 8 1 2 4 5 4 3 1 2 4 8 1 5 3 1 2 3 1 3 7
结果: 4 7 4 4 4 0 1 1