[国家集训队] 等差子序列

给定一个 \(1\)\(n\) 的排列 \(A\),判断是否存在 \(1 \leq p_1 < p_2 < \dots <p_{l} \leq n\),满足 \(l \geq 3\)\([a_{p_1},a_{p_2},\dots,a_{p_l}]\) 是等差数列。

\(T \leq 7\) 组数据,\(n \leq 5 \times 10^5\)

首先发现 \(l=3\)。若 \(l>3\),必然能够找到 \(l=3\) 的情况。

接下来考虑枚举中间的数,只需要检查两端是否分别出现 \(a_i-x\)\(a_i+x\) 即可。考虑其反面,即所有 \(a_i-x\)\(a_i+x\) 在同一端,此时我们考虑令 \(f_i=1\) 表示 \(i\) 在左侧,\(f_i=0\) 表示 \(i\) 在右侧,问题变为判定 \(f\) 关于 \(a_i\) 回文,哈希可以解决。

具体地,我们使用线段树,维护正反串哈希值即可。时间复杂度是 \(O(Tn \log n)\) 的。

#include<iostream>
#include<cstdio>
using namespace std;
const long long mod=998244353,base=233;
int p[500010];
long long pow_base[500010];
struct Node{
	int l,r;
	long long l_hash,r_hash;
}a[2000010];
Node merge(Node lhs,Node rhs){
	Node hs;
	hs.l=lhs.l;
	hs.r=rhs.r;
	hs.l_hash=lhs.l_hash+rhs.l_hash*pow_base[lhs.r-lhs.l+1]%mod;
	hs.l_hash%=mod;
	hs.r_hash=rhs.r_hash+lhs.r_hash*pow_base[rhs.r-rhs.l+1]%mod;
	hs.r_hash%=mod;
	return hs;
}
void build(int id,int l,int r){
	if(l==r){
		a[id].l=l;
		a[id].r=r;
		a[id].l_hash=a[id].r_hash=0;
	}
	else{
		int mid=(l+r)>>1;
		build(id*2,l,mid);
		build(id*2+1,mid+1,r);
		a[id]=merge(a[id*2],a[id*2+1]);
	}
}
void modify(int id,int pos){
	if(a[id].l==a[id].r){
		a[id].l_hash=a[id].r_hash=base;
		return ;
	}
	if(pos<=a[id*2].r){
		modify(id*2,pos);
	}
	else{
		modify(id*2+1,pos);
	}
	a[id]=merge(a[id*2],a[id*2+1]);
}
Node query(int id,int l,int r){
	if(l<=a[id].l  &&  a[id].r<=r){
		return a[id];
	}
	Node lans,rans;
	bool lflag=false,rflag=false;
	if(l<=a[id*2].r){
		lans=query(id*2,l,r);
		lflag=true; 
	}
	if(a[id*2+1].l<=r){
		rans=query(id*2+1,l,r);
		rflag=true;
	}
	if(lflag  &&  rflag){
		return merge(lans,rans);
	}
	else if(lflag){
		return lans;
	}
	else{
		return rans;
	}
}
int main(){
	int T;
	scanf("%d",&T);
	while(T--){
		int n;
		scanf("%d",&n);
		pow_base[0]=1;
		for(int i=1;i<=n;i++){
			pow_base[i]=pow_base[i-1]*base%mod;
			scanf("%d",&p[i]);
		}
		build(1,1,n);
		bool ok=false;
		for(int i=1;i<=n;i++){
			int len=min(p[i],n-p[i]+1);
			Node lans=query(1,p[i]-len+1,p[i]);
			Node rans=query(1,p[i],p[i]+len-1);
			if(lans.r_hash!=rans.l_hash){
				ok=true;
			}
			modify(1,p[i]);
		}
		if(ok){
			printf("Y\n");
		}
		else{
			printf("N\n");
		}
	}
	return 0;
}
posted @ 2025-12-05 10:56  Oken喵~  阅读(3)  评论(0)    收藏  举报