Gold Balanced Lineup
Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 12110 | Accepted: 3553 |
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
Hint
In the range from cow #3 to cow #6 (of size 4), each feature appears in exactly 2 cows in this range
题意:农夫john有n头小母牛,每头牛都有一些特点。假设有k个特点。并且用k位二进制表示,如果该位是1说明有此特点,
否则视为没有。求最长的范围L,满足在这L头牛中,它们的特点数量相等。用数据说明:
第几头 7 3 1 2 3(第几个特点)
1 7 ——> 1 1 1
2 6 ——> 1 1 0
3 7 ——> 1 1 1
4 2 ——> 0 1 0
5 1 ——> 0 0 1
6 4 ——> 1 0 0
7 2 ——> 0 1 0
可以看到从第3头到第6头牛每个特点的数量和均为2 ,而3-6是最远的范围。可以得出ans is four
思路:
题意已经明白了,怎么做呢,
1.将特点累加
第几头 7 3 1 2 3(第几个特点)
1 7 ——> 1 1 1
2 6 ——> 2 2 1
3 7 ——> 3 3 2
4 2 ——> 3 4 2
5 1 ——> 3 4 3
6 4 ——> 4 4 3
7 2 ——> 4 5 3
2.减去第1列或者其他列,相同即可。
第几头 7 3 1 2 3(第几个特点)
0 0 ——> 0 0 0
1 7 ——> 0 0 0
2 6 ——> 1 1 0
3 7 ——> 1 1 0
4 2 ——> 1 2 0
5 1 ——> 0 1 0
6 4 ——> 1 1 0
7 2 ——> 1 2 0
3.可以看出第2头到第6头都是1 1 0,所以6 - 2 = 4 is answer。 为什么这样呢?
因为第6头是累加的结果,即:s1+s2+s3+s4+s5+s6. 第2头:s1+s2 所以6-2 就剩下s3+s4+s5+s6。正是我们求的结果。
这也是为什么要加第0头的原因。如果读者不明白,可以看以下数据:
1 2
3
ans : 1
4.已经处理的差不多了,剩下的工作就是要离散(hash)查找了。我用的是linux 系统里的ElfHash方法。
code1:用vector模拟拉链法。跑了700ms左右
1 /*====================================================================== 2 * Author : kevin 3 * Filename : GlodBalancedLineup.cpp 4 * Creat time : 2014-07-24 11:39 5 * Description : 6 ========================================================================*/ 7 #include <iostream> 8 #include <algorithm> 9 #include <cstdio> 10 #include <cstring> 11 #include <queue> 12 #include <cmath> 13 #define clr(a,b) memset(a,b,sizeof(a)) 14 #define M 100005 15 #define MM 18979 16 using namespace std; 17 vector<int>hash[M]; 18 int s[M][35],n,k; 19 int ElfHash(char *name) //linux hash 20 { 21 int h = 0,g; 22 while(*name){ 23 h = (h<<4) + *name++; 24 g = h & 0xf0000000; 25 if(g) h ^= g>>24; 26 h &= ~g; 27 } 28 return (h%MM); 29 } 30 int slove(int ch[]) //转换成字符串并求hash值 31 { 32 char str[35]; 33 for(int i = 0; i < k; i++){ 34 str[i] = ‘F‘+ch[i]; 35 } 36 str[k] = ‘\0‘; 37 int key = ElfHash(str); 38 return key; 39 } 40 bool judge(int l,int h) //判断相等 41 { 42 for(int i = 0; i < k; i++){ 43 if(s[l][i] != s[h][i]){ 44 return false; 45 } 46 } 47 return true; 48 } 49 int Search(int key,int l) //查找 50 { 51 int len = hash[key].size(),max = 0,temp; 52 for(int i = 0; i < len; i++){ 53 if(judge(l,hash[key][i])){ 54 temp = fabs(l-hash[key][i]); 55 if(temp > max) max = temp; 56 } 57 } 58 hash[key].push_back(l); //向vector里追加元素 59 return max; 60 } 61 int main(int argc,char *argv[]) 62 { 63 scanf("%d%d",&n,&k); 64 int a = 0,max = 0; 65 clr(s,0); 66 for(int i = 1; i <= n; i++){ 67 scanf("%d",&a); 68 for(int j = 0; j < k; j++){ 69 int t = a&1; 70 if(t) s[i][j] = s[i-1][j]+1; 71 else s[i][j] = s[i-1][j]; 72 a = a>>1; 73 } 74 } 75 for(int i = 0; i <= n; i++){ 76 int q = s[i][0]; 77 for(int j = 0; j < k; j++){ 78 s[i][j] -= q; 79 } 80 int key = slove(s[i]); 81 int temp = Search(key,i); 82 if(temp > max) max = temp; 83 } 84 printf("%d\n",max); 85 return 0; 86 }
code2:用静态邻接表模拟拉链。跑了300ms左右
1 /*====================================================================== 2 * Author : kevin 3 * Filename : GlodBalancedLineup.cpp 4 * Creat time : 2014-07-24 11:39 5 * Description : 6 ========================================================================*/ 7 #include <iostream> 8 #include <algorithm> 9 #include <cstdio> 10 #include <cstring> 11 #include <queue> 12 #include <cmath> 13 #define clr(a,b) memset(a,b,sizeof(a)) 14 #define M 100005 15 #define MM 18979 16 using namespace std; 17 struct EdgeNode 18 { 19 int to,next; 20 }; 21 EdgeNode Edges[M]; 22 int s[M][35],n,k,head[M],cnt; 23 void AddEdges(int i,int j,int cnt) 24 { 25 Edges[cnt].to = j; 26 Edges[cnt].next = head[i]; 27 head[i] = cnt; 28 } 29 int ElfHash(char *name) 30 { 31 int h = 0,g; 32 while(*name){ 33 h = (h<<4) + *name++; 34 g = h & 0xf0000000; 35 if(g) h ^= g>>24; 36 h &= ~g; 37 } 38 return (h%MM); 39 } 40 int slove(int ch[]) 41 { 42 char str[35]; 43 for(int i = 0; i < k; i++){ 44 str[i] = ‘F‘+ch[i]; 45 } 46 str[k] = ‘\0‘; 47 int key = ElfHash(str); 48 return key; 49 } 50 bool judge(int l,int h) 51 { 52 for(int i = 0; i < k; i++){ 53 if(s[l][i] != s[h][i]){ 54 return false; 55 } 56 } 57 return true; 58 } 59 int Search(int key,int l) 60 { 61 int Max = 0,temp; 62 for(int k = head[key]; k != -1; k = Edges[k].next){ 63 if(judge(l,Edges[k].to)){ 64 temp = fabs(l-Edges[k].to); 65 if(temp > Max) Max = temp; 66 } 67 } 68 AddEdges(key,l,cnt++); 69 return Max; 70 } 71 int main(int argc,char *argv[]) 72 { 73 scanf("%d%d",&n,&k); 74 int a = 0,max = 0; 75 clr(s,0); 76 clr(head,-1); 77 cnt = 0; 78 for(int i = 1; i <= n; i++){ 79 scanf("%d",&a); 80 for(int j = 0; j < k; j++){ 81 int t = a&1; 82 if(t) s[i][j] = s[i-1][j]+1; 83 else s[i][j] = s[i-1][j]; 84 a = a>>1; 85 } 86 } 87 for(int i = 0; i <= n; i++){ 88 int q = s[i][0]; 89 for(int j = 0; j < k; j++){ 90 s[i][j] -= q; 91 } 92 int key = slove(s[i]); 93 int temp = Search(key,i); 94 if(temp > max) max = temp; 95 } 96 printf("%d\n",max); 97 return 0; 98 }
poj 3274 -- Gold Balanced Lineup