BZOJ2124: 等差子序列

题意:给一个 1 到 N 的排列{Ai},询问是否存在 1<=p1<p2<p3<p4<p5<…<pLen<=N(Len>=3),使得 Ap1,Ap2,Ap3,…ApLen 是一个等差序列。

按值建线段树,逐个插入,hash判断。

#include<bits/stdc++.h>
#define N (1<<15)
#define M (l+r>>1)
#define P (k<<1)
#define S (k<<1|1)
#define K l,r,k
#define L l,M,P
#define R M+1,r,S
#define Z \
int l=0,int r=n,int k=1
using namespace std;
int n,q;
typedef unsigned long long ull;
const ull base=23;
ull d[N],u[N],v[N];
void amend(int s,int t,Z){
	if(l==r)
		u[k]=v[k]=s;
	else{
		if(t<=M)
			amend(s,t,L);
		else
			amend(s,t,R);
		u[k]=u[P]+u[S]*d[M-l+1];
		v[k]=v[S]+v[P]*d[r-M];
	}
}
ull Q1(int s,int t,Z){
	return s==l&&t==r?u[k]:t<=M?Q1(s,t,L):s>M?Q1(s,t,R):Q1(s,M,L)+Q1(M+1,t,R)*d[M-s+1];
}
ull Q2(int s,int t,Z){
	return s==l&&t==r?v[k]:t<=M?Q2(s,t,L):s>M?Q2(s,t,R):Q2(M+1,t,R)+Q2(s,M,L)*d[t-M];
}
bool check(){
	memset(u,0,sizeof u);
	memset(v,0,sizeof v);
	static int a[N];
	for(int i=0;i!=n;++i)
		scanf("%d",a+i);
	for(int i=0;i!=n;amend(1,a[i++]))
		if(int j=min(a[i]-1,n-a[i]))
			if(Q1(a[i]+1,a[i]+j)^Q2(a[i]-j,a[i]-1))
				return 1;
	return 0;
}
int main(){
	d[0]=1;
	for(int i=1;i!=N;++i)
		d[i]=d[i-1]*base;
	for(scanf("%d",&q);q;--q){
		scanf("%d",&n);
		puts(check()?"Y":"N");
	}
}
posted @ 2016-05-15 20:15  f321dd  阅读(194)  评论(0编辑  收藏  举报