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

题目的等差子序列最少只要求长度为3,那么其实就转化为对于一个数是否存在左右各一个与它差值相等的一对数,比如1 4 3 2 5中1,5对3来说就如此。
这样的关系放到数轴上就是是否存在一对数到某数的距离相等。
由于题目明确是一个排列,也就是1到n所有数一定会出现一次,那么对于某数,它左边的数没有出现的数一定会出现在右边。
也就是说,若现在在第i项为x,第1到i-1个项中有一个y,1到n中存在2x-y,而此时若2x-y未出现在1到i-1中,那么2x-y一定会出现第i+1到n项中,这时满足条件,也就是存在等差子序列。
那么,如果需要不出现等差子序列,对第i项的x来说,就必须左右在能延长的范围内构成回文串,此时问题就变成了实时判断回文串。
对于这样的问题,可以使用字符串hash的思想,用hash来判回文串,接着套上线段树,用线段树维护hash值。

代码

#include<bits/stdc++.h>
#define maxn 500005
#define ll unsigned long long
using namespace std;
int T;
int n;
int a[maxn];
ll p[maxn];
struct segment_tree {
	int l,r;
	ll s1,s2;
} t[maxn<<2];
int ls(int x) {return x<<1;}
int rs(int x) {return x<<1|1;}
void tree_pre(int x,int l,int r) {
	t[x].l=l,t[x].r=r,t[x].s1=0,t[x].s2=0;
	if(l==r) return;
	int mid=(l+r)>>1;
	tree_pre(ls(x),l,mid);
	tree_pre(rs(x),mid+1,r);
}
void push_up(int x) {
	t[x].s1=t[ls(x)].s1*p[(t[rs(x)].r-t[rs(x)].l+1)]+t[rs(x)].s1;
	t[x].s2=t[rs(x)].s2*p[(t[ls(x)].r-t[ls(x)].l+1)]+t[ls(x)].s2;
}
void modify(int x,int des,ll val) {
	if(t[x].l==t[x].r) {t[x].s1=val,t[x].s2=val; return;}
	if(t[ls(x)].r>=des) modify(ls(x),des,val);
	else modify(rs(x),des,val);
	push_up(x);
}
ll query(int x,int l,int r,int k) {
	if(t[x].l>=l && t[x].r<=r) {if(k==1) return t[x].s1; return t[x].s2;}
	ll ans=0;
	if(t[ls(x)].r>=l && t[rs(x)].l<=r) {
		if(k==1) {
			ans=query(ls(x),l,r,1);
			ans=ans*p[(min(t[rs(x)].r,r)-t[ls(x)].r)]+query(rs(x),l,r,1);
		}
		else {
			ans=query(rs(x),l,r,2);
			ans=ans*p[(t[rs(x)].l-max(l,t[ls(x)].l))]+query(ls(x),l,r,2);
		}
	}
	else if(t[ls(x)].r>=l) ans=query(ls(x),l,r,k);
	else if(t[rs(x)].l<=r) ans=query(rs(x),l,r,k);
	return ans;
}
int main() {
//	freopen("P2757.in","r",stdin);
//	freopen("P2757.out","w",stdout);
	scanf("%d",&T);
	p[0]=1; for(int i=1;i<maxn;i++) p[i]=p[i-1]*131;
	while(T--) {
		scanf("%d",&n);
		tree_pre(1,1,n);
		bool TF=false;
		for(int i=1;i<=n;i++) scanf("%d",&a[i]);
		for(int i=1;i<=n;i++) {
			modify(1,a[i],1);
			int len=min(a[i]-1,n-a[i]); int l=a[i]-len,r=a[i]+len;
			if(query(1,l,r,1)!=query(1,l,r,2)) {TF=true; break;}
		}
		if(TF) printf("Y\n");
		else printf("N\n");
	}
	return 0;
}
posted @ 2024-02-17 21:18  Ian8877  阅读(17)  评论(0)    收藏  举报