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"); } }