「LOJ 6287」诗歌

题面

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;
}
posted @ 2020-10-14 18:09  cjTQX  阅读(151)  评论(0)    收藏  举报