BZOJ2124:等差子序列(线段树,hash)

Description

给一个1到N的排列{Ai},询问是否存在1<=p1<p2<p3<p4<p5<…<pLen<=N (Len>=3),
使得Ap1,Ap2,Ap3,…ApLen是一个等差序列。

Input

输入的第一行包含一个整数T,表示组数。
下接T组数据,每组第一行一个整数N,每组第二行为一个1到N的排列,数字两两之间用空格隔开。
N<=10000,T<=7

Output

对于每组数据,如果存在一个等差子序列,则输出一行“Y”,否则输出一行“N”。

Sample Input

2
3
1 3 2
3
3 2 1

Sample Output

N
Y

Solution

发现只用求是否存在长度为$3$的等差子序列就够了。

对于一个$a_i$,若$a_i-k$和$a_i+k$都在他前面出现才不会有$(a_i-k,a_i,a_i+k)$这个等差子序列出现。

所以可以从前往后枚举,出现为$1$未出现为$0$。可以用线段树维护区间$hash$判断以$a_i$为中心是否回文。

Code

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #define N (10009)
 5 #define LL unsigned long long
 6 using namespace std;
 7 
 8 int T,n,flag,a[N];
 9 LL Segt[N<<2][2],base[N];
10 
11 inline int read()
12 {
13     int x=0,w=1; char c=getchar();
14     while (c<'0' || c>'9') {if (c=='-') w=-1; c=getchar();}
15     while (c>='0' && c<='9') x=x*10+c-'0', c=getchar();
16     return x*w;
17 }
18 
19 void Update(int now,int l,int r,int x)
20 {
21     if (l==r) {Segt[now][0]=Segt[now][1]=1; return;}
22     int mid=(l+r)>>1;
23     if (x<=mid) Update(now<<1,l,mid,x);
24     else Update(now<<1|1,mid+1,r,x);
25     Segt[now][0]=Segt[now<<1][0]*base[r-mid]+Segt[now<<1|1][0];
26     Segt[now][1]=Segt[now<<1|1][1]*base[mid-l+1]+Segt[now<<1][1];
27 }
28 
29 LL Query(int now,int l,int r,int l1,int r1,int d)
30 {
31     if (l1<=l && r<=r1) return Segt[now][d];
32     int mid=(l+r)>>1;
33     if (r1<=mid) return Query(now<<1,l,mid,l1,r1,d);
34     else if (l1>mid) return Query(now<<1|1,mid+1,r,l1,r1,d);
35     else if(d==0) return Query(now<<1,l,mid,l1,mid,d)*base[r1-mid]+Query(now<<1|1,mid+1,r,mid+1,r1,d);
36     else if(d==1) return Query(now<<1|1,mid+1,r,mid+1,r1,d)*base[mid-l1+1]+Query(now<<1,l,mid,l1,mid,d);
37 }
38 
39 void Solve(int x)
40 {
41     Update(1,1,n,x);
42     if (x==1 || x==n) return;
43     int L=min(x-1,n-x);
44     LL lh=Query(1,1,n,x-L,x-1,0);
45     LL rh=Query(1,1,n,x+1,x+L,1);
46     if (lh!=rh) flag=1;
47 }
48 
49 int main()
50 {
51     T=read();
52     base[0]=1;
53     for (int i=1; i<=10000; ++i) base[i]=base[i-1]*1007;
54     while (T--)
55     {
56         memset(Segt,0,sizeof(Segt));
57         n=read(); flag=0;
58         for (int i=1; i<=n; ++i)
59         {
60             int x=read();
61             if (!flag) Solve(x);
62         }
63         puts(flag?"Y":"N");
64     }
65 }
posted @ 2019-03-13 17:19  Refun  阅读(233)  评论(0编辑  收藏  举报