bzoj 1702: [Usaco2007 Mar]Gold Balanced Lineup 平衡的队列——map+hash+转换
Description
N(1<=N<=100000)头牛,一共K(1<=K<=30)种特色,
每头牛有多种特色,用二进制01表示它的特色ID。比如特色ID为13(1101),
则它有第1、3、4种特色。[i,j]段被称为balanced当且仅当K种特色在[i,j]内
拥有次数相同。求最大的[i,j]段长度。
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
INPUT DETAILS:
The line has 7 cows with 3 features; the table below summarizes the
correspondence:
Feature 3: 1 1 1 0 0 1 0
Feature 2: 1 1 1 1 0 0 1
Feature 1: 1 0 1 0 1 0 0
Key: 7 6 7 2 1 4 2
Cow #: 1 2 3 4 5 6 7
7
6
7
2
1
4
2
INPUT DETAILS:
The line has 7 cows with 3 features; the table below summarizes the
correspondence:
Feature 3: 1 1 1 0 0 1 0
Feature 2: 1 1 1 1 0 0 1
Feature 1: 1 0 1 0 1 0 0
Key: 7 6 7 2 1 4 2
Cow #: 1 2 3 4 5 6 7
Sample Output
4
OUTPUT DETAILS:
In the range from cow #3 to cow #6 (of size 4), each feature appears
in exactly 2 cows in this range:
Feature 3: 1 0 0 1 -> two total
Feature 2: 1 1 0 0 -> two total
Feature 1: 1 0 1 0 -> two total
Key: 7 2 1 4
Cow #: 3 4 5 6
OUTPUT DETAILS:
In the range from cow #3 to cow #6 (of size 4), each feature appears
in exactly 2 cows in this range:
Feature 3: 1 0 0 1 -> two total
Feature 2: 1 1 0 0 -> two total
Feature 1: 1 0 1 0 -> two total
Key: 7 2 1 4
Cow #: 3 4 5 6
—————————————————————————————
这道题的话 因为颜色一共最多有30种 转换成2进制 每一位代表一种颜色
这样之后 如果存在 a1 b1 c1 d1 == a2 b2 c2 d2
那么容易证明
因为 d2-d1=c2-c1=b2-b1=a1-b1
以d这一颜色为例 d2-d1=a2-a1
所以 d2-a2==d1-a1 这样就转换成了只和自己有关
那么每一位同理处理就可以了
这样如果有两个前缀和 i 和 j 相同的话,那么i+1~j这一段的k种颜色出现次数一样多。
这样处理之后加一波hahs和map 判断这种前缀时候存在以及他的位置就可以了
#include<cstdio> #include<cstring> #include<algorithm> #include<map> #define LL unsigned long long const int M=2e5+7,P=233; int read(){ int ans=0,f=1,c=getchar(); while(c<'0'||c>'9'){if(c=='-') f=-1; c=getchar();} while(c>='0'&&c<='9'){ans=ans*10+(c-'0'); c=getchar();} return ans*f; } int n,k,ans; int d[M][35]; std::map<LL,int>q; int find(int x){ LL sum=0; for(int i=2;i<=k;i++) sum=sum*P+1LL*d[x][i]; if(!q[sum]&&sum) q[sum]=x; return q[sum]; } int main(){ n=read(); k=read(); for(int i=1;i<=n;i++){ int now=0,x=read(); for(;x;x>>=1) d[i][++now]=x&1; for(int j=1;j<=k;j++) d[i][j]+=d[i-1][j]; } for(int i=1;i<=n;i++){ for(int j=2;j<=k;j++) d[i][j]-=d[i][1]; ans=std::max(ans,i-find(i)); }printf("%d\n",ans); return 0; }