[BZOJ2124] 等差子序列
/*线段树维护区间HASH值*/
1 #include <cmath> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cstring> 5 #include <iostream> 6 #include <algorithm> 7 # define maxn 10010 8 # define p 31 9 using namespace std; 10 typedef unsigned long long ULL; 11 void fen(){cout<<"-------------------"<<endl;} 12 ULL px[maxn]; 13 int T,n; 14 void beg(){px[0]=1; for(int i=1;i<=10000;i++) px[i]=px[i-1]*p;} 15 int num[maxn]; 16 struct XDS{ 17 struct TR{ 18 int ls,rs,t; 19 ULL hs; 20 }tr[4*maxn]; 21 void pushup(int rt,int len1,int len2,int od){ 22 if(!od){ 23 tr[rt].hs=tr[rt<<1].hs*px[len2]+tr[rt<<1|1].hs; 24 } 25 else{ 26 tr[rt].hs=tr[rt<<1|1].hs*px[len1]+tr[rt<<1].hs; 27 } 28 } 29 void Add(int rt,int l,int r,int now,int od){ 30 if(l==r){tr[rt].t=1; tr[rt].hs=1; return;} 31 int mid=(l+r)>>1; 32 if(now<=mid) Add(rt<<1,l,mid,now,od); 33 else Add(rt<<1|1,mid+1,r,now,od); 34 pushup(rt,mid-l+1,r-mid,od); 35 } 36 ULL Query(int left,int right,int rt,int l,int r,int od){ 37 ULL ret=0; 38 if(left<=l && r<=right){ 39 if(!od){ret+=tr[rt].hs*px[right-r];} 40 else{ret+=tr[rt].hs*px[l-left];} 41 return ret; 42 } 43 int mid=(l+r)>>1; 44 if(left<=mid) ret+=Query(left,right,rt<<1,l,mid,od); 45 if(right>mid) ret+=Query(left,right,rt<<1|1,mid+1,r,od); 46 return ret; 47 } 48 }z,f; 49 void work(){ 50 memset(f.tr,0,sizeof(f.tr)); 51 memset(z.tr,0,sizeof(z.tr)); 52 int ak; 53 for(int i=1;i<=n;i++){ 54 ak=min(num[i]-1,n-num[i]); 55 z.Add(1,1,n,num[i],0); f.Add(1,1,n,num[i],1); 56 if(ak==0) continue; 57 ULL now1=z.Query(num[i]-ak,num[i]-1,1,1,n,0); 58 ULL now2=f.Query(num[i]+1,num[i]+ak,1,1,n,1); 59 if(now1!=now2){ 60 printf("Y\n"); return; 61 } 62 } 63 printf("N\n"); return; 64 } 65 int main(){ 66 // freopen("a.in","r",stdin); 67 scanf("%d",&T); 68 beg(); 69 while(T--){ 70 scanf("%d",&n); 71 for(int i=1;i<=n;i++) scanf("%d",&num[i]); 72 work(); 73 } 74 return 0; 75 }