$ \Rightarrow $ 戳我进BZOJ原题
Description
给一个 $ 1 $ 到 $ N $ 的排列 $ (A_i) $ ,询问是否存在 $ 1 \le p_1<p_2<p_3<p_4<p_5<…<p_ \le N (Len \ge 3) $ , 使得 $ A_,A_,A_,…A_{p_}是一个等差序列。
Input
输入的第一行包含一个整数 $ T $ ,表示组数。 接下来 $ T $ 组数据,每组第一行一个整数 $ N $ ,每组第二行为一个 $ 1 $ 到 $ N $ 的排列,数字两两之间用空格隔开。 $ N \le 10000,T \le 7 $
Output
对于每组数据,如果存在一个等差子序列,则输出一行“Y”,否则输出一行“N”。
Sample Input
231 3 233 2 1
###Sample Output
NY
思路
题目是要找 $ i<j<k $ ,使得 $ A_j - A_i = A_k - A_j $ ;
我们考虑按顺序插入 $ (A_i) $ ,对于我们当前位置 $ j $ ,如果有一个 $ A_i $ 已经出现了, 但是 $ A_k $ 还没有出现,因为是排列,所以这个 $ A_k $ 必然在后面,所以答案为“Y”;
我们用一个辅助数组 $ (B_i) $ ,按顺序如果 $ x $ 出现了,就标记为 $ 1 $ , 那么如果一个数 $ x $ 满足条件,那么必然有 $ B_ != B_{x+y} $ , 那么只需要判断以 $ x $ 为中心的最长的字符串是否为回文串即可;
因为如果不是回文串那么必然能找到一个 $ B_ != B_{x+y} $ ,所以答案为“Y”, 判断回文串可以用正反两边 $ hash $ ,然后 $ hash $ 值要动态修改,所以用树状数组和线段树都可以;
代码
/**************************************************************Problem: 2124User: PotremZLanguage: C++Result: AcceptedTime:2480 msMemory:2072 kb
****************************************************************/#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define int long long
#define Mod 1000000007
#define N 10005
inline int read() {register char ch;while(!isdigit(ch=getchar()));register int x=ch^'0';while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');return x;
}
int T,n,a[N],hash1[N<<2],hash2[N<<2],pows[N];
inline void pushup(int o,int len){int mid=len>>1;hash1[o]=(hash1[o<<1]*pows[mid]%Mod+hash1[o<<1|1])%Mod;hash2[o]=(hash2[o<<1]+hash2[o<<1|1]*pows[len-mid]%Mod)%Mod;
}
void updata(int o,int l,int r,int pos){if(l==r){hash1[o]=hash2[o]=1;return;}int mid=l+r>>1;if(pos<=mid) updata(o<<1,l,mid,pos);else updata(o<<1|1,mid+1,r,pos);pushup(o,r-l+1);
}
int query1(int o,int l,int r,int L,int R){if(L>R) return 0;if(L==l&&r==R) return hash1[o];int mid=l+r>>1;if(L>mid) return query1(o<<1|1,mid+1,r,L,R);else if(R<=mid) return query1(o<<1,l,mid,L,R);else return (query1(o<<1,l,mid,L,mid)*pows[R-mid]%Mod+query1(o<<1|1,mid+1,r,mid+1,R))%Mod;
}
int query2(int o,int l,int r,int L,int R){if(L>R) return 0;if(L==l&&r==R) return hash2[o];int mid=l+r>>1;if(L>mid) return query2(o<<1|1,mid+1,r,L,R);else if(R<=mid) return query2(o<<1,l,mid,L,R);else return (query2(o<<1,l,mid,L,mid)+query2(o<<1|1,mid+1,r,mid+1,R)*pows[mid-L+1]%Mod)%Mod;
}
signed main(){T=read(); pows[0]=1;for(int i=1;i<N;++i) pows[i]=(pows[i-1]<<1)%Mod;while(T--){n=read(); bool f=0;memset(hash1,0,sizeof(hash1));memset(hash2,0,sizeof(hash2));for(int i=1;i<=n;++i) a[i]=read(); for(int i=1;i<=n;++i){int len=min(n-a[i],a[i]-1);if(query1(1,1,n,a[i]-len,a[i]-1)!=query2(1,1,n,a[i]+1,a[i]+len)){ puts("Y"); break;}updata(1,1,n,a[i]);if(i==n) puts("N");}}return 0;
}