1. 程式人生 > >POJ 3274 -- Gold Balanced Lineup

POJ 3274 -- Gold Balanced Lineup

sent [] ext mean turn oid () all sed

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

USACO 2007 March Gold 題意: 技術分享圖片

解題思路:

牛的特征數組為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

POJ 3274 -- Gold Balanced Lineup