bzoj2124 等差子序列
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
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 }