题目
http://codeforces.com/contest/1446/problem/D2
题目大意
给你一个数组,问最长的一个区间使得这个区间的众数不唯一。
n
<
=
2
×
1
0
5
n<=2\times10^5
n<=2×105
a
i
<
=
n
a_i<=n
ai<=n
easy a i < = 100 a_i<=100 ai<=100
思路
考试的时候没有想出最重要的性质,变得完全不可做
性质:整个序列的众数一定是最优区间的众数之一。
下面我们令 D D D 表示整个序列的众数
证明:考虑反证法,假设答案区间 [ a , b ] [a,b] [a,b] 的众数不是 D D D,那么我们考虑扩展到 [ a − 1 , a − 2 … , b + 1 , b + 2 … ] [a-1,a-2…,b+1,b+2…] [a−1,a−2…,b+1,b+2…] 由于 D D D 出现的最多,所以一定会出现个数相等的情况,所以 [ a , b ] [a,b] [a,b] 不是答案区间。
先看 e a s y easy easy ,由于只有100种 a i a_i ai ,所以我们可以单独考虑每一个数,维护最长相等的区间。
h
a
r
d
hard
hard 考虑根号平衡规划
出现次数大于
n
\sqrt n
n 直接向easy那样做
出现次数小于
n
\sqrt n
n 区间段也<
n
\sqrt n
n,预处理胡暴力即可
代码
#include<bits/stdc++.h>
using namespace std;
const int N=1000005,M=200005;
int n,a[N],cn[N],c[N],c0[N],ans,maxn,p[N];
template<class I>
void Max(I&p,int q)
{
p=(p>q?p:q);
}
void ins(int x)
{
--c0[c[x]],++c[x],++c0[c[x]],Max(maxn,c[x]);
}
void del(int x)
{
--c0[c[x]],--c[x],++c0[c[x]],maxn-=(c0[maxn]==0);
}
int main()
{
scanf("%d",&n);
int mx=0;
for(int i=1; i<=n; i++) scanf("%d",&a[i]),++cn[a[i]],cn[a[i]]>cn[mx]?mx=a[i]:0;
if(cn[mx]==n) return putchar('0'),0;
int lim=(cn[mx]<512?cn[mx]:512);
for(int i=1; i<=n; i++)
if(i!=mx&&cn[i]>=512)
{
for(int j=-n; j<=n; j++) p[j+M]=-1;
for(int sum=p[M]=0,j=1; j<=n; j++)
sum+=(a[j]==mx),sum-=(a[j]==i),~p[sum+M]?Max(ans,j-p[sum+M]),0:p[sum+M]=j;
}
for(int i=1; i<=lim; i++)
{
for(int j=1; j<=n; j++) c[j]=c0[j]=0;
c0[maxn=0]=n;
for(int j=1,k=1,x=0; j<=n; j++)
{
while(k<=n&&x+(a[k]==mx)<=i) ins(a[k]),x+=(a[k]==mx),++k;
c0[maxn]>=2?Max(ans,k-j),0:0,del(a[j]),x-=(a[j]==mx);
}
}
printf("%d",ans);
}