bzoj2124 等差子序列 線段樹+雜湊
阿新 • • 發佈:2018-12-14
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
考慮暴力怎麼做,我們列舉中項,列舉首項,用桶判斷是否存在,這樣是Tn2的 可以發現我們列舉j的時候和做卷積是一樣的,考慮用bitset優化 記字首桶為A,字尾桶為B。對於a[i]我們在A中a[i]的位置插入1,在B中20000-a[i]的位置插入1 若B>>(20000-a[i])&A不全為0說明存在這樣三個等差數列,於是這樣做是的
題解做法:我們開一個桶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;
}