题目链接: L O J # 10042 \rm LOJ\ \#10042 LOJ #10042
使用双指针扫描法。设左、右指针分别为
l
,
r
l,r
l,r ,那么在
r
r
r 右移的过程中维护
l
l
l 即可。
维护方法:若存在
x
∈
[
l
,
r
)
∩
Z
x\in[l,r)\cap\Z
x∈[l,r)∩Z ,使
a
x
=
a
r
a_x=a_r
ax=ar (显然最多存在一个
x
x
x ),则使
l
=
x
+
1
l=x+1
l=x+1 ,否则不变。每次维护后要更新最优解。
l
=
x
+
1
l=x+1
l=x+1 可以保证避免冲突且答案最大化。
用哈希表 E E E 记录某个数 t t t 最后一次出现的位置,那么只需支持查表、插入、修改即可。
#include<cstdio>
#include<cctype>
#define getc (l==r&&(r=(l=c)+fread(c,1,1<<21,stdin),l==r)?EOF:*l++)
const int P=1145141,N=1000010; //P为哈希模数
int n,x,j=1,ans=1,t,cnt,a[N],last[P]; //j相当于左指针l
struct node { int x,i,pre; }E[N];
char c[1<<21],*l=c,*r=c;
inline int read() { //fread快读
int x=0; char ch=getc;
while (!isdigit(ch)) ch=getc;
while (isdigit(ch)) { x=x*10+(ch^48); ch=getc; }
return x;
}
inline int max(int x,int y) { return (x>y?x:y); }
int find(int x,int t) { //查表
for (int i=last[t]; i; i=E[i].pre)
if (E[i].x==x) return i;
return 0; //没有出现过则返回0
}
int main() {
n=read();
for (int i=1; i<=n; ++i) { //i相当于右指针r
a[i]=read(); x=a[i]%P; t=find(a[i],x);
if (t) { j=max(j,E[t].i+1); E[t].i=i; }
//注意实现时我们不能保证E[t].i>j,所以这里要取max
else { E[++cnt]=(node){a[i],i,last[x]}; last[x]=cnt; }
//没有出现过时无需移动指针,但要在表里插入新元素
ans=max(ans,i-j+1); //更新最优解
}
printf("%d\n",ans);
return 0;
}
时间复杂度不会算,反正比
Θ
(
n
log
n
)
\Theta(n\log n)
Θ(nlogn) 快就对了
在
L
O
J
\rm LOJ
LOJ 上应该算是挺快的 (还不是因为用了fread快读)