Codeforces452F Permutation -- 线段树 + Hash

来源:互联网 发布:大数据 精准医疗 案例 编辑:程序博客网 时间:2024/06/10 20:21

假如不存在长度大于等于 3 的等差数列,那么对于第 i 个数 aiaikai+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 1000000007int 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;}