1. 程式人生 > >Bzoj2124(p5364): 等差子序列

Bzoj2124(p5364): 等差子序列

題目描述

給一個1到N的排列{Ai},詢問是否存在1<=p1<p2<p3<p4<p5<…<pLen<=N (Len>=3),

使得Ap1,Ap2,Ap3,…ApLen是一個等差序列。

輸入

輸入的第一行包含一個整數T,表示組數。

下接T組資料,每組第一行一個整數N,每組第二行為一個1到N的排列,數字兩兩之間用空格隔開。

N<=10000,T<=7

輸出

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

樣例輸入

2
3
1 3 2
3
3 2 1

樣例輸出

N
Y 

考慮什麼時候不存在等差數列
把出現過的數字對應位置賦成1,沒出現過的為0
那麼掃到i時,以a[i]為中心的串如果是迴文,那麼就不存在以a[i]為中心的等差數列
考慮用線段樹維護正反兩種hash值,詳情看程式碼吧233
這題做的時候一次忘關除錯資訊了,然後刪的時候還不小心刪多了。。。(ノへ ̄、)
 1 #include<cstdio>
 2 #include<cstring>
 3 #define ull unsigned long long
 4 using namespace std;
 5 int T,n,a[10005];
 6 ull sum1[50000
],sum2[50000],hsh[10005]; 7 void add(int x,int l,int r,int q){ 8 if(l==q&&r==q){ 9 sum1[x]=sum2[x]=1; 10 return; 11 } 12 int mid=(l+r)/2; 13 if(q<=mid)add(x+x,l,mid,q); 14 else add(x+x+1,mid+1,r,q); 15 sum1[x]=sum1[x+x]*hsh[r-mid]+sum1[x+x+1]; 16 sum2[x]=sum2[x+x]+sum2[x+x+1
]*hsh[mid-l+1]; 17 } 18 ull query(int x,int l,int r,int L,int R,int t){ 19 if(l==L&&r==R){ 20 if(t==1)return sum1[x]; 21 else return sum2[x]; 22 } 23 int mid=(l+r)/2; 24 if(R<=mid)return query(x+x,l,mid,L,R,t); 25 else if(L>mid)return query(x+x+1,mid+1,r,L,R,t); 26 else{ 27 if(t==1)return query(x+x,l,mid,L,mid,t)*hsh[R-mid]+query(x+x+1,mid+1,r,mid+1,R,t); 28 else return query(x+x,l,mid,L,mid,t)+query(x+x+1,mid+1,r,mid+1,R,t)*hsh[mid-L+1]; 29 } 30 } 31 ull A,B; 32 int main(){ 33 scanf("%d",&T); 34 hsh[0]=1; 35 for(int i=1;i<=10002;i++)hsh[i]=hsh[i-1]*131; 36 while(T--){ 37 bool ok=1; 38 scanf("%d",&n); 39 for(int i=1;i<=n;i++)scanf("%d",&a[i]); 40 for(int i=1;i<=n;i++){ 41 if(ok){ 42 if(a[i]<=n/2){ 43 A=query(1,1,n,1,2*a[i]-1,1); 44 B=query(1,1,n,1,2*a[i]-1,0); 45 } 46 else{ 47 A=query(1,1,n,2*a[i]-n,n,1); 48 B=query(1,1,n,2*a[i]-n,n,0); 49 } 50 if(A!=B)ok=0; 51 add(1,1,n,a[i]); 52 } 53 else break; 54 } 55 if(ok)printf("N\n"); 56 else printf("Y\n"); 57 memset(sum1,0,sizeof(sum1)); 58 memset(sum2,0,sizeof(sum2)); 59 } 60 return 0; 61 }
View Code