1. 程式人生 > >bzoj 2124 等差子序列 樹狀數組維護hash+回文串

bzoj 2124 等差子序列 樹狀數組維護hash+回文串

修改 pan mod clr oid struct content output -a

等差子序列

Time Limit: 3 Sec Memory Limit: 259 MB
Submit: 1919 Solved: 713
[Submit][Status][Discuss]

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

HINT

因此,我們構造一個輔助數組b,其中x如果出現過,那麽b[x]=1;否則b[x]=0。因此如果x滿足條件,那麽必然存在一個數y使得b[x-y]!=b[x+y];然後我們發現如果把b看成一個字符串,那麽實際上就是判斷以x為中心的極長字符串是否是回文串,如果不是那麽顯然存在y使得b[x-y]!=b[x+y],那麽就可以輸出‘Y‘。快速的字符串比較不妨使用hash,然後因為需要修改那麽就用兩個樹狀數組分別維護它所在區間正著和倒著的hash值即可。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #define ll long long
 5 #define mod 1000000007
 6 #define N 10005
 7 using namespace std;
 8 
 9 int n,a[N],pw[N];
10 struct bit_node{
11     int c[N];
12     void clr(){ memset(c,0,sizeof(c)); }
13     void add(int
x){ 14 int i; for (i=x; i<=n; i+=i&-i) c[i]=(c[i]+pw[i-x])%mod; 15 } 16 int getsum(int x){ 17 int i,t=0; for (i=x; i; i^=i&-i) t=((ll)c[i]*pw[x-i]+t)%mod; 18 return t; 19 } 20 int qry(int x,int y){ 21 int p=getsum(x-1),q=getsum(y); 22 return (q-(ll)p*pw[y-x+1]%mod+mod)%mod; 23 } 24 }bit1,bit2; 25 int main(){ 26 int cas,i; scanf("%d",&cas); 27 pw[0]=1; for (i=1; i<=10000; i++) pw[i]=(ll)pw[i-1]*12347%mod; 28 while (cas--){ 29 scanf("%d",&n); int x; 30 for (i=1; i<=n; i++) scanf("%d",&a[i]); 31 bit1.clr(); bit2.clr(); 32 for (i=1; i<=n; i++){ 33 x=min(a[i]-1,n-a[i]); 34 if (x && bit1.qry(a[i]-x,a[i]-1)!=bit2.qry(n-a[i]-x+1,n-a[i])) break; 35 bit1.add(a[i]); bit2.add(n-a[i]+1); 36 } 37 puts((i>n)?"N":"Y"); 38 } 39 }

bzoj 2124 等差子序列 樹狀數組維護hash+回文串