给一个1到N的排列{Ai},询问是否存在1<=p1=3),使得Ap1,Ap2,Ap3,…ApLen是一个等差序列。
给一个1到N的排列{Ai},询问是否存在1<=p1=3),使得Ap1,Ap2,Ap3,…ApLen是一个等差序列。
输入的第一行包含一个整数T,表示组数。下接T组数据,每组第一行一个整数N,每组第二行为一个1到N的排列,数字两两之间用空格隔开。
对于每组数据,如果存在一个等差子序列,则输出一行“Y”,否则输出一行“N”。
对于100%的数据,N<=10000,T<=7
我们只需要判断是否存在一个长度为3的等差子序列就好...
首先我们有一个很机智的想法...我们枚举中间的数x,判断是否存在x-y和x+y分别在x两边...我们从左向右扫描当前数字记为中间数字,维护一个vis数组,vis[i]=1代表i在当前数字之前出现过,=0代表没有出现过...然后只要当前数字的左右两边的01串不一样就代表存在一组合法解...
这种判断回文串的问题可以通过hash解决,但是我们要动态维护hash值,所以要借助树状数组或者线段树...
记得一定要开long long...
1 #include<algorithm> 2 #include<iostream> 3 #include<cstring> 4 #include<cstdio> 5 //by NeighThorn 6 #define int long long 7 using namespace std; 8 9 const int maxn=10000+5,Mod=1e9+7; 10 11 int n,cas,flag,p[maxn]; 12 13 struct Tree{ 14 15 long long tr[maxn]; 16 17 inline void clear(void){ 18 memset(tr,0,sizeof(tr)); 19 } 20 21 inline void insert(int x,int y){ 22 int lala=x; 23 for(;x<=n;x+=x&-x) 24 (tr[x]+=y*p[x-lala])%=Mod; 25 } 26 27 inline int query(int x){ 28 int lala=x,res=0; 29 for(;x;x-=x&-x) 30 (res+=((long long)tr[x]*p[lala-x])%Mod)%Mod; 31 return res; 32 } 33 34 inline int qry(int l,int r){ 35 return ((long long)query(r)-(long long)query(l-1)*p[r-l+1]%Mod+Mod)%Mod; 36 } 37 38 }a,b; 39 40 signed main(void){ 41 scanf("%lld",&cas);p[0]=1; 42 for(int i=1;i<=10000;i++) 43 p[i]=(p[i-1]<<1)%Mod; 44 while(cas--){ 45 scanf("%lld",&n);flag=0; 46 a.clear();b.clear(); 47 for(int i=1,x;i<=n;i++){ 48 scanf("%lld",&x); 49 if(flag) 50 continue; 51 int lala=min(x-1,n-x); 52 if(lala&&a.qry(x-lala,x-1)!=b.qry(n-(x+lala)+1,n-(x+1)+1)) 53 puts("Y"),flag=1; 54 a.insert(x,1),b.insert(n-x+1,1); 55 } 56 if(!flag) 57 puts("N"); 58 } 59 return 0; 60 }
By NeighThorn
原文:http://www.cnblogs.com/neighthorn/p/6265737.html