码迷,mamicode.com
首页 > 其他好文 > 详细

CF452F Permutation 题解

时间:2020-10-29 09:34:03      阅读:14      评论:0      收藏:0      [点我收藏+]

标签:line   ati   题解   ons   做了   push   http   tin   线段树   

Link

CF452F Permutation

Solve

先转化一下题意,对于一个\(a[i]\)我们判断如果存在一个\(a[i]+k\)\(a[i]-k\)\(a[i]\)的异侧,那么就存在一个解,输出\(yes\),如果对于每个\(a[i]\)都不存在,就输出\(no\)

如何判断是否存在\(a[i]+k\)\(a[i]-k\)的位置,我们想到了回文,处理每个\(a[i]\)时,我们把\(a[i]\)这个位置打上\(1\),如果此时的序列不是以\(a[i]\)为中心的回文,那么肯定有一个对应的\(a[i]+k\)或者\(a[i]-k\)\(a[i]\)后面,就存在解了,如果是回文,那么对于这个\(a[i]\)每一个k,\(a[i]+k\)\(a[i]-k\)都在\(a[i]\)同侧了。

如何维护回文,很容易的想到线段树+哈希,一个回文串,正着哈希和反过来哈希的结果是一样的,我们就建两棵线段树,一棵表示正着哈希,一棵表示反着哈希,反着哈希的树统计时就把左儿子和右儿子交换就好了,相当于把线段树做了一次对称(这么说也不够严谨,感性理解一下就好了)。

Code

#include<bits/stdc++.h>
using namespace std;
const int maxn=3e5+5,TT=1e9+7,bas=27;
typedef long long LL;
int N,a[maxn];
LL pw[maxn];
struct node{
	LL val;
	int len;
	node(const LL v=0,const int l=0){val=v;len=1;}
}ta[maxn<<2],tb[maxn<<2];
inline int read(){
	int ret=0,f=1;char ch=getchar();
	while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-f;ch=getchar();}
	while(ch<=‘9‘&&ch>=‘0‘)ret=ret*10+ch-‘0‘,ch=getchar();
	return ret*f;
}
node merge(node l,node r){
	node ret;
	ret.val=(l.val*pw[r.len]%TT+r.val)%TT;
	ret.len=l.len+r.len;
	return ret;
}

void pushup(int k){
	ta[k]=merge(ta[k<<1],ta[k<<1|1]);
	tb[k]=merge(tb[k<<1|1],tb[k<<1]);
}

void update(int k,int l,int r,int x){
	if(l==r){
		ta[k]=tb[k]=node(1,1);
		return ;
	}
	int mid=l+r>>1;
	if(x<=mid)update(k<<1,l,mid,x);
	else update(k<<1|1,mid+1,r,x);
	pushup(k);
}

node query1(int k,int l,int r,int x,int y){
	if(x<=l&&r<=y)return ta[k];
	int mid=r+l>>1;
	if(y<=mid)return query1(k<<1,l,mid,x,y);
	if(mid<x)return query1(k<<1|1,mid+1,r,x,y);
	return merge(query1(k<<1,l,mid,x,mid),query1(k<<1|1,mid+1,r,mid+1,y));
}

node query2(int k,int l,int r,int x,int y){
	if(x<=l&&r<=y)return tb[k];
	int mid=r+l>>1;
	if(y<=mid)return query2(k<<1,l,mid,x,y);
	if(mid<x)return query2(k<<1|1,mid+1,r,x,y);
	return merge(query2(k<<1|1,mid+1,r,mid+1,y),query2(k<<1,l,mid,x,mid));
}

void build(int k,int l,int r){
	if(l==r){
		ta[k]=tb[k]=node(0,1);
		return ;
	}
	int mid=r+l>>1;
	build(k<<1,l,mid);build(k<<1|1,mid+1,r);
	pushup(k);
}

int main(){
	freopen("CF452F.in","r",stdin);
	freopen("CF452F.out","w",stdout);
	N=read();
	pw[0]=1;
	for(int i=1;i<=N;i++)pw[i]=pw[i-1]*bas%TT;
	build(1,1,N);
	for(int i=1;i<=N;i++){
		int x=read();
		update(1,1,N,x);
		int k=min(x-1,N-x);
		if(k<=0) continue;
		if(query1(1,1,N,x-k,x-1).val!=
		query2(1,1,N,x+1,x+k).val){
			printf("YES\n");
			return 0;
		}
	}
	printf("NO\n");
	return 0;
}

CF452F Permutation 题解

标签:line   ati   题解   ons   做了   push   http   tin   线段树   

原文地址:https://www.cnblogs.com/martian148/p/13889058.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!