bzoj2124 等差子序列
Posted wfj_2048
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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
3
1 3 2
3
3 2 1
Sample Output
N
Y
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 }
以上是关于bzoj2124 等差子序列的主要内容,如果未能解决你的问题,请参考以下文章