[线段树+哈希] Codeforces 452F. Permutation

来源:互联网 发布:c语言 property get 编辑:程序博客网 时间:2024/06/07 16:50

要注意到这是一个排列,1~n每个数都出现一次,不用上这个条件就做不了。

对于一个数 x , 所有的xk, x+k 一定在 x 的同一侧,否则就输出YES 。所以就有了这样的解法:从左到右扫描序列,设当前到i , 已经把 1i1 的数都丢到权值线段树中了。若此时xk, x+k 有一个是1,有一个是0,则说明找到了。也就是只要比较一下权值线段树 a[i] 两侧的两段的哈希值即可。

#include<cstdio>#include<algorithm>#include<cstring>#define mp(x,y) make_pair(x,y)#define Fir first#define Sec secondusing namespace std;typedef unsigned long long uLL;const uLL maxn=300005,con=2333;uLL pw[maxn];struct node{    uLL h,rh; node* ch[2];    node(){ ch[0]=ch[1]=0; h=rh=0; }    void maintain(int len){        h=ch[0]->h*pw[len-(len+1>>1)]+ch[1]->h;        rh=ch[1]->rh*pw[len+1>>1]+ch[0]->rh;    }} *root;typedef node* P_node;void Updata(P_node p,int L,int R,int pos){    if(pos<L||R<pos) return;    if(L==R){ p->h=p->rh=1; return; }    int mid=(L+R)>>1;    Updata(p->ch[0],L,mid,pos); Updata(p->ch[1],mid+1,R,pos);    p->maintain(R-L+1);}pair<uLL,int> Merge(pair<uLL,int> A,pair<uLL,int> B){ return mp(A.Fir*pw[B.Sec]+B.Fir,A.Sec+B.Sec); }pair<uLL,int> Query_hsh(P_node p,int L,int R,int qL,int qR){    if(R<qL||qR<L) return mp(0,0);    if(qL<=L&&R<=qR) return mp(p->h,R-L+1);     int mid=(L+R)>>1;    return Merge(Query_hsh(p->ch[0],L,mid,qL,qR),Query_hsh(p->ch[1],mid+1,R,qL,qR));}pair<uLL,int> Query_rhsh(P_node p,int L,int R,int qL,int qR){    if(R<qL||qR<L) return mp(0,0);    if(qL<=L&&R<=qR) return mp(p->rh,R-L+1);     int mid=(L+R)>>1;    return Merge(Query_rhsh(p->ch[1],mid+1,R,qL,qR),Query_rhsh(p->ch[0],L,mid,qL,qR));}P_node Build(int L,int R){    P_node p=new node();    if(L==R) return p;    int mid=(L+R)>>1;    p->ch[0]=Build(L,mid); p->ch[1]=Build(mid+1,R);    return p;}int n,a[maxn];int main(){    freopen("cf452F.in","r",stdin);    freopen("cf452F.out","w",stdout);    pw[0]=1;for(int i=1;i<=300000;i++) pw[i]=pw[i-1]*con;    scanf("%d",&n);    root=Build(1,n);    for(int i=1;i<=n;i++) scanf("%d",&a[i]);    for(int i=1;i<=n;i++){        int len=min(a[i]-1,n-a[i]);        if(Query_hsh(root,1,n,a[i]-len,a[i]-1).Fir!=Query_rhsh(root,1,n,a[i]+1,a[i]+len).Fir) return printf("YES\n"),0;        Updata(root,1,n,a[i]);    }    printf("NO\n");    return 0;}
原创粉丝点击