Gold Balanced Lineup
| Time Limit: 2000MS |
|
Memory Limit: 65536K |
| Total Submissions: 7565 |
|
Accepted: 2236 |
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 onlyK 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 featurei.
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 cowsi..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 37672142
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
很有趣的一道題。枚舉區間肯定是要逾時的(因為無論如何最佳化複雜度都至少n^2)。區間[i,j]之和sum(i,j)不好處理可以轉化成sum(0,j)-sum(0,i-1),關鍵是如何判斷減出結果和個特徵是數量是相等的。注意到兩個和向量之差(a1,a2,a3...)-(b1,b2,b3...)=(a1-b1,a2-b2,a3-b3...) 若a1-b1=a2-b2=a3-b3=...,則(a2-a1,a3-a1,a4-a1...)=(b2-b1,b3-b1,b4-b1...),因此可以對這個差向量Hash!
從序列開始累加,看這個差是否出現過,如果出現就計算最早出現的位置和當前位置的差,取最長者。注意要在Hash表中加一項(0,0,0...),代碼注釋中說明,寫得很渣,供參考。
#include <iostream>#include <cstdio>using namespace std;int n;int k;const int HSIZE=69061;struct HashNode {HashNode() {next=0;}int dif[31];int first_app;HashNode* next;};bool same(int*a,int* b){for(int i=0; i<k-1; ++i) {if(a[i]!=b[i])return false;}return true;}HashNode* htable[HSIZE]={0};int hash(int* a){long long r=0;for(int i=0; i<k-1; ++i) {r = r*131+a[i];}return (r&0x7FFFFFFF)%HSIZE;}int query(int* dif,int app) //查詢,不存在就添加{int h = hash(dif);HashNode* cur=htable[h];while(cur) {if(same(cur->dif,dif))return app-cur->first_app;cur=cur->next;}cur = new HashNode();cur->next = htable[h];cur->first_app = app;copy(dif,dif+k-1,cur->dif);htable[h] = cur;return -1;}int main(){cin>>n>>k;int tmp;int dif[31]={0};int dist;int mlen=0;int fir;query(dif,-1); //添加(0,0,0...),否則若第一個元素a1=a2=a3...答案會少1for(int i=0; i<n; ++i) {scanf("%d",&tmp);fir = tmp&1;tmp>>=1;for(int b=1; b<k; ++b) {dif[b-1] += (tmp&1)-fir;tmp>>=1;}if((dist=query(dif,i))>0){if(dist>mlen){mlen = dist;}}}cout<<mlen<<endl;}
--------------------------------------------------------------------------------
My Blog: 點擊開啟連結