Codeforces452F Permutation -- 线段树 + Hash

假如不存在长度大于等于 3 的等差数列,那么对于第 i 个数 ai aik ai+k 一定都在 i 的左边或右边。那么建一棵权值线段树,从左往右扫一次,判断一下 [xmaxk,x1] [x+1,x+maxk] 反转后 Hash 值是否相等。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define N 300010
#define P 127
#define M 1000000007
int c[2][N<<2],p[N];
int i,j,k,n,m,x;
inline void Up(int x,int l){
    c[0][x]=(c[0][x<<1]+1ll*c[0][x<<1|1]*p[l+1>>1]%M)%M;
    c[1][x]=(c[1][x<<1|1]+1ll*c[1][x<<1]*p[l>>1]%M)%M;
}
inline void Update(int x,int l,int r,int y){
    if(l==r){
        c[0][x]=c[1][x]=1;
        return;
    }
    int Mid=l+r>>1;
    if(y<=Mid)Update(x<<1,l,Mid,y);else Update(x<<1|1,Mid+1,r,y);
    Up(x,r-l+1);
}
inline int Query(int x,int l,int r,int L,int R,int d){
    if(l>R||r<L)return 0;
    if(l>=L&&r<=R)return 1ll*c[d][x]*(d?p[R-r]:p[l-L])%M;
    int Mid=l+r>>1;
    return (Query(x<<1|1,Mid+1,r,L,R,d)+Query(x<<1,l,Mid,L,R,d))%M;
}
int main(){
    scanf("%d",&n);
    for(i=p[0]=1;i<n;i++)p[i]=1ll*p[i-1]*P%M;
    for(i=1;i<=n;i++){
        scanf("%d",&x);
        if(x<=n/2){
            if(Query(1,1,n,1,x-1,0)!=Query(1,1,n,x+1,x*2-1,1)){
                puts("YES");
                return 0;
            }
        }else{
            if(Query(1,1,n,x+1,n,0)!=Query(1,1,n,x*2-n,x-1,1)){
                puts("YES");
                return 0;
            }
        }
        Update(1,1,n,x);
    }
    puts("NO");
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值