POJ 3274 -- Gold Balanced Lineup

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

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

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

 

posted @ 2018-02-11 09:17  卉卉卉大爷  阅读(228)  评论(0编辑  收藏  举报