bzoj2124 等差子序列

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

 

正解:树状数组+$hash$。

超级神题系列。。

这道题实际上是问能否找到一组$j<i<k$,使得$a[i]-a[j]=a[k]-a[i]$。

考虑枚举中间的那个$i$,我们要找到一个公差$x$,使得$a[i]-x$出现过,而$a[i]+x$没有出现过。

那么维护一个数组$b$,$b[i]=1$表示$i$出现过,否则没有出现过,于是只要有$b[a[i]-x]!=b[a[i]+x]$就行了。

考虑把$b$变成一个字符串,那么如果以$x$为中心的极长串不是回文串,那么就有一组合法情况。

那么我们维护一个正的字符串和反的字符串,因为有单点修改,所以我们用树状数组维护字符串的$hash$值就行了。

查询的时候直接比较$a[i]$的左边串和右边的倒串是否相等即可。

 

 1 #include <bits/stdc++.h>
 2 #define il inline
 3 #define RG register
 4 #define ll long long
 5 #define ull unsigned long long
 6 #define N (100010)
 7 #define lb(x) (x & -x)
 8 
 9 using namespace std;
10 
11 int a[N],n,fg;
12 ull bin[N];
13 
14 il int gi(){
15   RG int x=0,q=1; RG char ch=getchar();
16   while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
17   if (ch=='-') q=-1,ch=getchar();
18   while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar();
19   return q*x;
20 }
21 
22 struct bit{
23   
24   ull c[N];
25   
26   il void init(){ memset(c,0,sizeof(c)); return; }
27   
28   il void add(RG int x){
29     for (RG int i=x;i<=n;i+=lb(i)) c[i]+=bin[i-x]; return;
30   }
31   
32   il ull query(RG int x){
33     RG ull res=0; for (RG int i=x;i;i^=lb(i)) res+=c[i]*bin[x-i]; return res;
34   }
35   
36   il ull calc(RG int l,RG int r){
37     RG ull hsh1=query(l-1),hsh2=query(r);
38     return hsh2-hsh1*bin[r-l+1];
39   }
40   
41 }bit1,bit2;
42 
43 il void work(){
44   bit1.init(),bit2.init(),n=gi(),fg=0;
45   for (RG int i=1;i<=n;++i) a[i]=gi();
46   for (RG int i=1,len;i<=n;++i){
47     len=min(a[i]-1,n-a[i]);
48     if (len && bit1.calc(a[i]-len,a[i]-1)!=bit2.calc(n-a[i]-len+1,n-a[i])){ fg=1; break; }
49     bit1.add(a[i]),bit2.add(n-a[i]+1);
50   }
51   puts(fg ? "Y" : "N"); return;
52 }
53 
54 int main(){
55 #ifndef ONLINE_JUDGE
56   freopen("sequence.in","r",stdin);
57   freopen("sequence.out","w",stdout);
58 #endif
59   bin[0]=1; for (RG int i=1;i<N;++i) bin[i]=bin[i-1]*10007;
60   RG int T=gi();
61   while (T--) work();
62   return 0;
63 }

 

posted @ 2017-11-24 19:02  wfj_2048  阅读(213)  评论(0编辑  收藏  举报