1. 程式人生 > >bzoj2124 等差子序列 線段樹+雜湊

bzoj2124 等差子序列 線段樹+雜湊

Description

給一個1到N的排列{Ai},詢問是否存在1<=p1<p2<p3<p4<p5<…<pLen<=N (Len>=3), 使得Ap1,Ap2,Ap3,…ApLen是一個等差序列。 輸入的第一行包含一個整數T,表示組數。 下接T組資料,每組第一行一個整數N,每組第二行為一個1到N的排列,數字兩兩之間用空格隔開。 N<=10000,T<=7

Solution

考慮暴力怎麼做,我們列舉中項aja_j,列舉首項ai(ij)a_i (i\leq j ),用桶判斷是否存在ak=2ajai(jk)a_k=2a_j-a_i (j\leq k)

,這樣是Tn2的 可以發現我們列舉j的時候和做卷積是一樣的,考慮用bitset優化 記字首桶為A,字尾桶為B。對於a[i]我們在A中a[i]的位置插入1,在B中20000-a[i]的位置插入1 若B>>(20000-a[i])&A不全為0說明存在這樣三個等差數列,於是這樣做是Tn232T\frac{n^2}{32}

題解做法:我們開一個桶b[],依次插入a。若a[i]是中項則桶中一定存在j使得b[j]!=b[2*i-j]。 我們把b看成字串,a[i]為中項即b不存在以i為中心的迴文子串,這個東西可以雜湊判斷。我們要資瓷插入、求區間雜湊,於是上線段樹就可以了

Code

#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <bitset>
#define rep(i,st,ed) for (register int i=st;i<=ed;++i)
#define fill(x,t) memset(x,t,sizeof(x))

typedef long long LL;
const int MOD=2147483647;
const int N=10005;

LL sum[N<<2][2],wjp[N]
; int a[N]; inline int read() { int x=0,v=1; char ch=getchar(); for (;ch<'0'||ch>'9';v=(ch=='-')?(-1):(v),ch=getchar()); for (;ch<='9'&&ch>='0';x=x*10+ch-'0',ch=getchar()); return x*v; } void modify(int now,int tl,int tr,int x) { if (tl==tr) return (void) (sum[now][0]=sum[now][1]=1); int mid=(tl+tr)>>1; if (x<=mid) modify(now<<1,tl,mid,x); else modify(now<<1|1,mid+1,tr,x); sum[now][0]=(1LL*sum[now<<1][0]*wjp[tr-mid]%MOD+sum[now<<1|1][0])%MOD; sum[now][1]=(1LL*sum[now<<1|1][1]*wjp[mid-tl+1]%MOD+sum[now<<1][1])%MOD; } LL query(int now,int tl,int tr,int l,int r,int opt) { if (r<l) return 0; if (tl==l&&tr==r) return sum[now][opt]; int mid=(tl+tr)>>1; if (r<=mid) return query(now<<1,tl,mid,l,r,opt); if (l>mid) return query(now<<1|1,mid+1,tr,l,r,opt); int qx=query(now<<1,tl,mid,l,mid,opt); int qy=query(now<<1|1,mid+1,tr,mid+1,r,opt); if (!opt) return (1LL*qx*wjp[3,r-mid]%MOD+qy)%MOD; return (1LL*qy*wjp[mid-l+1]%MOD+qx)%MOD; } void build(int now,int tl,int tr) { sum[now][0]=sum[now][1]=0; if (tl==tr) return ; int mid=(tl+tr)>>1; build(now<<1,tl,mid); build(now<<1|1,mid+1,tr); } int main(void) { wjp[0]=1; rep(i,1,N-1) wjp[i]=wjp[i-1]*3LL%MOD; for (int T=read();T--;) { int n=read(),flag=false; build(1,1,n); rep(i,1,n) a[i]=read(); rep(i,1,n) { int len=std:: min(a[i],n-a[i]+1); LL qx=query(1,1,n,a[i]-len+1,a[i]-1,0); LL qy=query(1,1,n,a[i]+1,a[i]+len-1,1); if (qx!=qy) { // printf("%d\n", i); flag=true; break; } modify(1,1,n,a[i]); } (!flag)?puts("N"):puts("Y"); } return 0; }