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

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
—————————————————————————————
这道题的话 因为颜色一共最多有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;
}
View Code

 

 
posted @ 2017-09-15 14:26  友人Aqwq  阅读(210)  评论(0编辑  收藏  举报