看上去无从下手,把式子写出来冷静一下:
对于区间 $[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; }