BZOJ1702. [Usaco2007 Mar]Gold Balanced Lineup 平衡的队列

传送门

看上去无从下手,把式子写出来冷静一下:

对于区间 $[i,j]$ ,要满足要求的条件为:

$sum[i][1]-sum[j-1][1]=sum[i][2]-sum[j-1][2]$

$sum[i][1]-sum[j-1][1]=sum[i][3]-sum[j-1][3]$

...

$sum[i][1]-sum[j-1][1]=sum[i][k]-sum[j-1][k]$

其中 $sum[i][j]$ 表示 $[1,i]$  区间内特色 $j$ 的出现次数

把下标一样的放一起:

$sum[j-1][2]-sum[j-1][1]=sum[i][2]-sum[i][1]$

$sum[j-1][3]-sum[j-1][1]=sum[i][3]-sum[i][1]$

...

$sum[j-1][k]-sum[j-1][1]=sum[i][k]-sum[i][k]$

发现只要满足 $sum[i][p]-sum[i][1]=sum[j][p]-sum[j][1], \forall p \in [1,k]$ 

所以直接搞一个 $map$ 维护就行,我感觉把状态 $hash$ 不太稳啊,所以直接搞个结构体枚举判断就好了

注意是前缀和所以要记得把 $0$ 加入 $map$ !

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<map>
using namespace std;
typedef long long ll;
inline int read()
{
    int x=0,f=1; char ch=getchar();
    while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
    while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
    return x*f;
}
const int N=1e5+7;
int n,K,ans;
struct dat{
    int a[31];
    dat () { memset(a,0,sizeof(a)); }
    inline dat F()
    {
        dat res;
        for(int i=1;i<=K;i++) res.a[i]=a[i]-a[1];
        return res;
    }
    inline bool operator < (const dat &tmp) const {
        for(int i=1;i<=K;i++)
            if(a[i]!=tmp.a[i]) return a[i]<tmp.a[i];
        return 0;
    }
}C[N],sum;
map <dat,int> mp;
int main()
{
    n=read(),K=read(); int a;
    for(int i=1;i<=n;i++)
    {
        a=read();
        for(int j=1;j<=K;a>>=1,j++) C[i].a[j]=a&1;
    }
    mp[sum.F()]=1;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=K;j++) sum.a[j]+=C[i].a[j];
        dat p=sum.F();
        if(mp[p]) ans=max(ans,i-(mp[p]-1));
        else mp[p]=i+1;
    }
    printf("%d\n",ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/LLTYYC/p/11408401.html