zoukankan      html  css  js  c++  java
  • BZOJ 2124:等差子序列

    简要题意:

    给定一个长度为n的排列pi,问是否存在一个长度大于等于3的等差子序列。

    思路:

    首先,很显然的一点,我们只需要考虑是否存在长度等于3的等差子序列即可。

    而且要注意到本题非常特殊的一点是排列,这意味着[1..n]中的每个数都恰好出现一次且仅出现一次。

    那么当我们枚举等差子序列中间的那一项时,不妨设为a[mid],

    那么假设等差子序列的第一项为a[l](l<mid),那么如果2*a[mid]-a[l]>=1 且 2*a[mid]-a[l]<=n,

    那么2*a[mid]-a[l]要么落在mid左侧,要么落在mid右侧。

    如果落在mid右侧,那么长度等于3的等差子序列即存在。

    由于时限的关系,O(n^2)的做法会超时,因此我们显然不能在枚举中间项的同时再枚举第一项;

    因此此时优化的点在于不枚举第一项,而是采用一种替代的方法,不通过枚举来得到我们需要的效果。

    我们需要用一种数据结构来存储在mid左侧出现过的数字。

    并且支持快速查找每一个[1..n]的数字x,2*a[mid]-x是否也同时在这个数据结构中出现。

    如果2*a[mid]-x不在这个数据结构出现,且1<=2*a[mid]-x<=n,说明2*a[mid]-x一定在mid的右侧出现,那么说明此时我们需要的等差子序列出现了。

    这启发我们用权值线段树来完成这个工作,

    我们可以用一个01权值线段树来记录所有出现在mid左侧的数字,即x这个数值出现,则线段树上x的位置的值为1,否则为0;

    那么相当于我们需要判断的是我们的01权值线段树是否关于a[mid]值对称。(当然细节需要注意,超出[1..n]的部分需要丢掉)

    快速判断两个区间是否相同,这就属于字符串hash的功能范围内了。

    因此,我们在权值线段树上同时维护区间从左到右的Hash值,从右到左的Hash值,当查询的时候只需要快速判断一下a[mid]两侧的Hash值是否相同即可。

    如果不同,说明存在我们需要的等差子序列。

    当我们移动mid时,对权值线段树做的修改就是单点修改,比较方便维护两个Hash值的变化。

    至此,本题已经完成。时间复杂度为O(NlogN)。

    #include<bits/stdc++.h>
    #define lson(p) p<<1
    #define rson(p) p<<1|1
    #define rep(i,a,b) for (int i=a;i<b;i++)
    #define per(i,a,b) for (int i=a-1;i>=b;i--)
    #define all(v) (v).begin() (v).end()
    #define fi first
    #define se second
    #define SZ(x) ((int)(x).size())
    #define pb push_back
    #define mp make_pair
    using namespace std;
    typedef long long ll;
    typedef double db;
    typedef pair<int,int> PII;
    typedef vector<int> VI;
    clock_t startTime;
    mt19937 mrand(random_device{}());
    const int mod=1e9+7;
    const int maxn=1e4+10;
    int pw[maxn];
    int a[maxn];
    int T,n;
    db getCurrentTime()
    {
        return (db)(clock()-startTime)/CLOCKS_PER_SEC;
    }
    struct node
    {
        int Lhash,Rhash;
        int len;
        int v;
    }b[maxn<<2];
    void pushup(int p)
    {
        b[p].Lhash=(1LL*b[lson(p)].Lhash*pw[b[rson(p)].len]%mod+b[rson(p)].Lhash)%mod;
        b[p].Rhash=(1LL*b[rson(p)].Rhash*pw[b[lson(p)].len]%mod+b[lson(p)].Rhash)%mod;
        b[p].len=b[lson(p)].len+b[rson(p)].len;
    }
    void build(int p,int l,int r)
    {
        if (l==r) {
            b[p].len=1;
            b[p].Lhash=b[p].Rhash=0;
            b[p].v=0;
            return ;
        }
        int mid=(l+r)>>1;
        build(lson(p),l,mid);
        build(rson(p),mid+1,r);
        pushup(p);
    }
    void modify(int p,int l,int r,int pos)
    {
        if (l==r) {
            b[p].v=1;
            b[p].Lhash=b[p].Rhash=1;
            return ;
        }
        int mid=(l+r)>>1;
        if (pos<=mid) modify(lson(p),l,mid,pos);
        else modify(rson(p),mid+1,r,pos);
        pushup(p);
    }
    node getHash(int p,int l,int r,int L,int R)
    {
        if (L>R) {
            node e;
            e.Lhash=e.Rhash=0;
            return e;
        }
        if (L<=l&&r<=R) return b[p];
        int mid=(l+r)>>1;
        if (R<=mid) return getHash(lson(p),l,mid,L,R);
        else if (L>mid) return getHash(rson(p),mid+1,r,L,R);
        else {
            node e1=getHash(lson(p),l,mid,L,R);
            node e2=getHash(rson(p),mid+1,r,L,R);
            node e;
            e.Lhash=(1LL*e1.Lhash*pw[e2.len]%mod+e2.Lhash)%mod;
            e.Rhash=(1LL*e2.Rhash*pw[e1.len]%mod+e1.Rhash)%mod;
            e.len=e1.len+e2.len;
            return e;
        }
    }
    int main()
    {
        pw[0]=1;
        for (int i=1;i<maxn;i++) pw[i]=1LL*pw[i-1]*233%mod;
        scanf("%d",&T);
        while (T--) {
            scanf("%d",&n);
            for (int i=1;i<=n;i++) scanf("%d",&a[i]);
            build(1,1,n);
            bool bo=false;
            for (int i=1;i<=n;i++) {
                int x=min(a[i]-1,n-a[i]);
                node l=getHash(1,1,n,a[i]-x,a[i]-1);
                node r=getHash(1,1,n,a[i]+1,a[i]+x);
                if (l.Rhash!=r.Lhash) {
                    bo=true; break;
                }
                modify(1,1,n,a[i]);
            }
            if (bo) printf("Y
    ");
            else printf("N
    ");
        }
        return 0;
    }
    

      

  • 相关阅读:
    The Quad
    将OrCAD Capture CIS的设计文件(.dsn)导入到PADS Logic VX.2.3
    OrCAD Capture CIS 16.6 将版本16.6的设计文件另存为版本16.2的设计文件
    Eclipse IDE 添加jar包到Java工程中
    PADS Logic VX.2.3 修改软件界面语言
    切换Allegro PCB Editor
    Allegro PCB Design GXL (legacy) 将brd文件另存为低版本文件
    Allegro PCB Design GXL (legacy) 设置自动保存brd文件
    Could not create an acl object: Role '16'
    windows 下apache开启FastCGI
  • 原文地址:https://www.cnblogs.com/xyw5vplus1/p/14586343.html
Copyright © 2011-2022 走看看