SP744 LPERMUT - Longest Permutation

SP744 LPERMUT - Longest Permutation

找到一个最长的子段,满足其重排后是 \(1,2,3,4...k\) ,其中 \(k\) 是子段长度。

一道思维题。

首先我们考虑找到这样的段的性质:序列长度为 \(k\) 且互不相同。

然后我们可以推出一个结论:这个序列中一定只包含一个某一个数

于是我们原数列中的 1 就相当于是把原数列分成了很多的段,于是如果我们可以每次以 1 为起点,然后向两边中的某一边扫一遍的话,就能够 \(O(n)\) 解决这个问题。

但是我们势必是要枚举两边的,这样做就是 \(O(n^2)\) 的了,于是我们可以考虑枚举一边,然后 \(O(1)\) 算另一边最长对应可以到达的位置。

这个该怎么算呢,我们假设目前匹配到的左端点是 \(pos\) ,然后当前右端点是 \(i\) (枚举 \(i\)),然后枚举下一个 \(i\) 的时候,答案的 \(pos\) 单调不增(如果此时会发生 \(pos++\) 了就代表遇到了两个同样的了。)。

那么一个点对于另外一个点的增加/减少有单调性,很明显就是双指针扫一遍了。

于是最后我们的复杂度为 \(O(n)\)

代码:

#include<bits/stdc++.h>
using namespace std;
template <typename T>
inline void read(T &x){
	x=0;char ch=getchar();bool f=false;
	while(!isdigit(ch)){if(ch=='-'){f=true;}ch=getchar();}
	while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	x=f?-x:x;
	return ;
}
template <typename T>
inline void write(T x){
	if(x<0) putchar('-'),x=-x;
	if(x>9) write(x/10);
	putchar(x%10^48);
	return ;
}
const int N=3e5+5;
int n,a[N],ans;
int posl[N],posr[N],pos[N],Max[N],Maxpos[N];
void work(int s,int L,int R){
	if(ans==0)ans=1;
	Max[s]=a[s];
	for(int i=s-1;i>=L;i--) Max[i]=max(Max[i+1],a[i]);
	for(int i=s+1;i<=R;i++) Max[i]=max(Max[i-1],a[i]);
	Maxpos[s]=posl[s];
	for(int i=s-1;i>=L;i--) Maxpos[i]=max(Maxpos[i+1],posl[i]);
	for(int i=s+1;i<=R;i++) Maxpos[i]=max(Maxpos[i-1],posl[i]);
	for(int i=s-1;i>=L;i--){
    	if(Maxpos[i]>=i) continue;
    	int len=Max[i],r=i+len-1;
    	if(r>R) continue;
    	if(Maxpos[r]>=i||Max[r]>=Max[i]) continue;
    	if(len>ans) ans=len;
	}
	for(int i=s+1;i<=R;i++){
		if(Maxpos[i]>=s) continue;
		int len=Max[i],l=i-len+1;
		if(l<L) continue;
		if(Maxpos[l]>=l||Maxpos[i]>=l||Max[l]>=Max[i]) continue;
		if(len>ans) ans=len;
	}
	return ;
}
int main(){
	read(n);
	for(int i=1;i<=n;i++) read(a[i]);
	for(int i=1;i<=n;i++) posl[i]=pos[a[i]],pos[a[i]]=i;
	for(int i=1;i<=n;i++) pos[i]=n+1;
	for(int i=n;i>=1;i--) posr[i]=pos[a[i]],pos[a[i]]=i;
	for(int i=1;i<=n;i++) if(a[i]==1) work(i,posl[i]+1,posr[i]-1);
	write(ans);
	return 0;
}
posted @ 2021-04-21 08:27  __Anchor  阅读(45)  评论(0编辑  收藏  举报