BZOJ-2124: 等差子序列

[文章目录]

Description

给一个1到N的排列{Ai},询问是否存在1<=p1< p2< p3< p4< p5<…< pLen<=N (Len>=3),使得Ap1,Ap2,Ap3,…ApLen是一个等差序列。N<=10000,T<=7

分段hash+桶。
考虑我们将每个数扔进桶里,枚举到一个x。如果x不构成任意一个等差数列当且仅当对于每两个值x-d,x+d在桶中都出现或者没出现,也就是说桶里关于x对称。那么我们维护桶的hash值,每次判断关于当前值ai是否回文,如果回文则修改,继续判断下一个,反之则说明存在等差数列的三项。时间复杂度O(nlogn)

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef unsigned long long ull;
const int bas=233;
int n,a[10010];
ull bin[10010];
struct hass
{
    ull h1,h2;
};
struct seg
{
    ull h1[40010],h2[40010];
    void clear(){memset(h1,0,sizeof h1); memset(h2,0,sizeof h2);}
    void pushup(int pos,int l1,int l2)
    {
        h1[pos]=h1[pos<<1]+h1[pos<<1|1]*bin[l1];
        h2[pos]=h2[pos<<1|1]+h2[pos<<1]*bin[l2];
    }
    void fix(int pos,int l,int r,int x)
    {
        if(l==r) {h1[pos]=h2[pos]=1;return;}
        int mid=(l+r)>>1;
        if(x<=mid) fix(pos<<1,l,mid,x);
        else fix(pos<<1|1,mid+1,r,x);
        pushup(pos,mid-l+1,r-mid);
    }
    hass query(int pos,int l,int r,int x,int y)
    {
        if(x<=l&&y>=r) return (hass){h1[pos],h2[pos]};
        int mid=(l+r)>>1;
        if(y<=mid) return query(pos<<1,l,mid,x,y);
        else if(x>mid) return query(pos<<1|1,mid+1,r,x,y);
        else
        {
            hass ls=query(pos<<1,l,mid,x,y);
            hass rs=query(pos<<1|1,mid+1,r,x,y);
            return (hass){ls.h1+rs.h1*bin[mid-max(x,l)+1],rs.h2+ls.h2*bin[min(r,y)-mid]};
            //一定要取max和min,因为当前区间不一定就是大于[x,y]
        }
    }
}s;
int main()
{
    int T; scanf("%d",&T);
    bin[0]=1; for(int i=1;i<=10000;++i) bin[i]=bin[i-1]*bas;
    while(T--)
    {
        scanf("%d",&n); for(int i=1;i<=n;++i) scanf("%d",a+i);
        s.clear(); bool fl=0; int len; hass ch;
        for(int i=1;i<=n;++i)
        {
            len=min(a[i]-1,n-a[i]);
            ch=s.query(1,1,n,a[i]-len,a[i]+len);
            if(ch.h1!=ch.h2) {fl=1; break; }
            s.fix(1,1,n,a[i]);
        }
        if(fl) puts("Y");
        else puts("N");
    }
    return 0;
}

发表评论

邮箱地址不会被公开。 必填项已用*标注