1. 程式人生 > >bzoj2124 等差子序列

bzoj2124 等差子序列

stream 數據 amp con cstring scrip != main else

Description

給一個1到N的排列{Ai},詢問是否存在1<=p1<p2<p3<p4<p5<…<pLen<=N (Len>=3), 使得Ap1,Ap2,Ap3,…ApLen是一個等差序列。

Input

輸入的第一行包含一個整數T,表示組數。 下接T組數據,每組第一行一個整數N,每組第二行為一個1到N的排列,數字兩兩之間用空格隔開。 N<=10000,T<=7

Output

對於每組數據,如果存在一個等差子序列,則輸出一行“Y”,否則輸出一行“N”。

Sample Input

2
3
1 3 2
3
3 2 1

Sample Output

N
Y

只要找到一個長度為3的就可以了

也就是j<i<k,a[i]-a[j]=a[k]-a[i]

也就是a[i]-x和a[i]+x在i不同側

b[a[i]]=1表示在前面出現過,0表示沒有

因為是排列,所以等價於b[a[i]-x]!=b[a[i]+x]

把它看作一個以a[i]為中心的最長串,如果不是回文串,那麽顯然存在答案

用樹狀數組維護字符串hash,正向反向維護2個

 1 #include<iostream>
 2 #include<cstdio>
 3
#include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 using namespace std; 7 typedef unsigned long long ull; 8 const int N=10007; 9 const int p=10007; 10 ull bin[N],c1[N],c2[N]; 11 int n,a[N]; 12 void add1(int x) 13 {int i; 14 for (i=x;i<=n;i+=(i&(-i)))
15 c1[i]+=bin[i-x]; 16 } 17 void add2(int x) 18 {int i; 19 for (i=x;i<=n;i+=(i&(-i))) 20 c2[i]+=bin[i-x]; 21 } 22 ull query1(int x) 23 {ull s=0; 24 int i; 25 for (i=x;i;i-=(i&(-i))) 26 s+=c1[i]*bin[x-i]; 27 return s; 28 } 29 ull query2(int x) 30 {ull s=0; 31 int i; 32 for (i=x;i;i-=(i&(-i))) 33 s+=c2[i]*bin[x-i]; 34 return s; 35 } 36 ull cal1(int l,int r) 37 { 38 ull h1=query1(l-1),h2=query1(r); 39 return h2-bin[r-l+1]*h1; 40 } 41 ull cal2(int l,int r) 42 { 43 ull h1=query2(l-1),h2=query2(r); 44 return h2-bin[r-l+1]*h1; 45 } 46 int main() 47 {int T,i,flag; 48 cin>>T; 49 bin[0]=1; 50 for (i=1;i<N;i++) 51 bin[i]=bin[i-1]*p; 52 while (T--) 53 { 54 cin>>n; 55 memset(c1,0,sizeof(c1)); 56 memset(c2,0,sizeof(c2)); 57 for (i=1;i<=n;i++) 58 { 59 scanf("%d",&a[i]); 60 } 61 flag=0; 62 for (i=1;i<=n;i++) 63 { 64 int L=min(a[i]-1,n-a[i]); 65 if (L&&cal1(a[i]-L,a[i]-1)!=cal2(n-a[i]-L+1,n-a[i])) 66 {flag=1;break;} 67 add1(a[i]); 68 add2(n-a[i]+1); 69 } 70 if (flag) cout<<"Y"<<endl; 71 else cout<<"N"<<endl; 72 } 73 }

bzoj2124 等差子序列