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
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
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 rangeSource
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