「一本通 2.1 练习 8」收集雪花

题目链接: 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快读)


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值