题意
不同的雪花往往有不同的形状。在北方的同学想将雪花收集起来,作为礼物送给在南方的同学们。一共有 n 个时刻,给出每个时刻下落雪花的形状,用不同的整数表示不同的形状。在收集的过程中,同学们不希望有重复的雪花。你可以从任意 a 时刻开始,在 b 时刻停止。 a 到 b 时刻中间的雪花也都将被收集。他们希望收集的雪花最多。
\(1≤n≤10^6,0≤x_i≤10^9\)
分析
参照jklover的题解。
首先需要离散化或hash,将值域控制在1e6的级别.
然后,若直接上主席树,每次二分答案,枚举左端点,是O(nlog2n)的,十分弱智巨.
优秀的做法是Two Pointers.维护两个指针l,r,不断往后跳,同时用类似于莫队的方法维护当前区间内颜色种类数目.合法时更新答案.
这样每个指针最多跳n次,一共跳2n次,相当优秀.
代码
#include<bits/stdc++.h>
#define rg register
#define il inline
#define co const
template<class T>il T read()
{
rg T data=0;
rg int w=1;
rg char ch=getchar();
while(!isdigit(ch))
{
if(ch=='-')
w=-1;
ch=getchar();
}
while(isdigit(ch))
{
data=data*10+ch-'0';
ch=getchar();
}
return data*w;
}
template<class T>il T read(rg T&x)
{
return x=read<T>();
}
typedef long long ll;
using namespace std;
co int N=1e6+1;
int n,x[N],y[N],cnt;
int t[N],cols;
void ins(int p)
{
if(++t[x[p]]==1)
++cols;
}
void del(int p)
{
if(--t[x[p]]==0)
--cols;
}
int main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
read(n);
for(int i=1;i<=n;++i)
y[i]=read(x[i]);
sort(y+1,y+n+1);
cnt=unique(y+1,y+n+1)-(y+1);
for(int i=1;i<=n;++i)
x[i]=lower_bound(y+1,y+cnt+1,x[i])-y;
int l=1,r=1,ans=0;
for(;r<=n;++r)
{
ins(r);
while(l<=r&&cols!=r-l+1)
del(l++);
if(cols==r-l+1)
ans=max(ans,r-l+1);
}
printf("%d\n",ans);
return 0;
}