题面
LOJ 6287
Solution
- 枚举中间点\(j\),题目即求是否存在\(m\)使\(a[j]-m\)与\(a[j]+m\)分别在\(j\)两侧。
- 对于\(j\)左侧任意一个点\(i\),都将\(t[a[i]]\)赋值为1,那么若以\(j\)为中心的\(len\)最大的字符串不是回文子串,则必然有解。
- 建2棵线段树维护哈希值即可判断回文子串
Code
#include<bits/stdc++.h>
using namespace std;
const int N=3e5+10;
const int mod=1e9+7;
const int base=31;
inline int read(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
return x*f;
}
#define lc (p<<1)
#define rc (p<<1|1)
int n,a[N],b[N];
struct Tree{
int v[N<<2];
inline void change(int p,int l,int r,int x){
if(l==r){
v[p]=1;
return ;
}
int mid=(l+r)>>1;
if(x<=mid) change(lc,l,mid,x);
else change(rc,mid+1,r,x);
v[p]=(1ll*v[lc]*b[r-mid]%mod+v[rc])%mod;
}
inline int query(int p,int l,int r,int ql,int qr){
if(l>=ql&&r<=qr)
return v[p];
int mid=(l+r)>>1,ans1=0,ans2=0;
if(ql<=mid) ans1=query(lc,l,mid,ql,qr);
if(qr>mid) ans2=query(rc,mid+1,r,ql,qr);
if(ql<=mid&&qr>mid) return (1ll*ans1*b[min(qr,r)-mid]%mod+ans2)%mod;
else if(ql<=mid) return ans1;
else return ans2;
}
}L,R;
int main(){
n=read();
for(int i=1;i<=n;++i) a[i]=read();
b[0]=1;for(int i=1;i<=n;++i) b[i]=1ll*b[i-1]*base%mod;
for(int i=1;i<=n;++i){
int len=min(a[i],n-a[i]+1);
if(L.query(1,1,n,a[i],a[i]+len-1)!=R.query(1,1,n,n-a[i]+1,n-a[i]+len)){
puts("YES");
return 0;
}
L.change(1,1,n,a[i]);
R.change(1,1,n,n-a[i]+1);
}
puts("NO");
return 0;
}