Description
给一个1到N的排列{Ai},询问是否存在1<=p1=3),使得Ap1,Ap2,Ap3,…ApLen是一个等差序列。
Input
输入的第一行包含一个整数T,表示组数。下接T组数据,每组第一行一个整数N,每组第二行为一个1到N的排列,数字两两之间用空格隔开。
Output
对于每组数据,如果存在一个等差子序列,则输出一行“Y”,否则输出一行“N”。
Sample Input
2
3
1 3 2
3
3 2 1
Sample Output
N
Y
HINT
对于100%的数据,N<=10000,T<=7
首先觉得题目不错(2013年我竟然在wikioi过了,代码还很短,然后把代码翻出来,发现是暴力n方加优化代码。。。。。。汗,我当时怎么想的)
今天看到题目觉得没什么想法,于是就翻了题解
就是维护每一个数字a[i]之前出现a[i]-1,a[i]-2,a[i]-3...的出现情况和a[i]+1,a[i]+2,a[i]+3...的出现情况(用二进制)
如果这两个二进制数的第k位不同,那么就是a[i]-k在a[i]前出现了,a[i]+k在a[i]之后出现或者a[i]+k在a[i]前出现了,a[i]-k在a[i]之后出现,所以我们只要判断两个二进制不同,就可以用hash值来判断了(不放心的话可以做两个hash),用线段树维护hash值就行了
1 const 2 maxn=10010; 3 h=1000000007; 4 type 5 node=record 6 l,r,lc,rc:longint; 7 h1,h2:int64; 8 end; 9 var 10 f:array[0..maxn*2]of node; 11 a:array[0..maxn]of longint; 12 p:array[0..maxn]of int64; 13 t,n,tot:longint; 14 15 function min(x,y:longint):longint; 16 begin 17 if xy then exit(x); 24 exit(y); 25 end; 26 27 procedure add(x,now:longint); 28 var 29 mid:longint; 30 begin 31 if f[now].l=f[now].r then 32 begin 33 f[now].h1:=1; 34 f[now].h2:=1; 35 exit; 36 end; 37 mid:=(f[now].l+f[now].r)>>1; 38 if x>mid then add(x,f[now].rc) 39 else add(x,f[now].lc); 40 f[now].h1:=(f[f[now].lc].h1*p[f[now].r-mid]+f[f[now].rc].h1)mod h; 41 f[now].h2:=(f[f[now].rc].h2*p[mid-f[now].l+1]+f[f[now].lc].h2)mod h; 42 end; 43 44 procedure build(l,r:longint); 45 var 46 now,mid:longint; 47 begin 48 inc(tot); 49 now:=tot; 50 f[now].l:=l; 51 f[now].r:=r; 52 f[now].h1:=0; 53 f[now].h2:=0; 54 f[now].lc:=0; 55 f[now].rc:=0; 56 if l=r then exit; 57 mid:=(l+r)>>1; 58 f[now].lc:=tot+1; 59 build(l,mid); 60 f[now].rc:=tot+1; 61 build(mid+1,r); 62 end; 63 64 function hash1(l,r,now:longint):int64; 65 var 66 mid:longint; 67 begin 68 if (l<=f[now].l) and (r>=f[now].r) then exit(f[now].h1); 69 mid:=(f[now].l+f[now].r)>>1; 70 if l>mid then exit(hash1(l,r,f[now].rc)); 71 if r<=mid then exit(hash1(l,r,f[now].lc)); 72 exit((hash1(l,r,f[now].lc)*p[min(r,f[now].r)-mid]+hash1(l,r,f[now].rc))mod h); 73 end; 74 75 function hash2(l,r,now:longint):int64; 76 var 77 mid:longint; 78 begin 79 if (l<=f[now].l) and (r>=f[now].r) then exit(f[now].h2); 80 mid:=(f[now].l+f[now].r)>>1; 81 if l>mid then exit(hash2(l,r,f[now].rc)); 82 if r<=mid then exit(hash2(l,r,f[now].lc)); 83 exit((hash2(l,r,f[now].rc)*p[mid-max(l,f[now].l)+1]+hash2(l,r,f[now].lc))mod h); 84 end; 85 86 procedure main; 87 var 88 i:longint; 89 begin 90 read(n); 91 for i:=1 to n do 92 read(a[i]); 93 tot:=0; 94 build(1,n); 95 for i:=2 to n-1 do 96 begin 97 add(a[i-1],1); 98 if hash1(a[i]-min(a[i]-1,n-a[i]),a[i],1)=hash2(a[i],a[i]+min(a[i]-1,n-a[i]),1) then continue; 99 writeln('Y');100 exit;101 end;102 writeln('N');103 end;104 105 begin106 p[0]:=1;107 for t:=1 to maxn do108 p[t]:=p[t-1]*2 mod h;109 read(t);110 while t>0 do111 begin112 dec(t);113 main;114 end;115 end.