• 等差子序列


    等差子序列

    等差序列只要找三个数就行

    x,y,z

    想法枚举中间数y O(n) , 公差 d O(n) 看看y-d和y+d是不是在y的同侧(预处理每个数的pos)

    这样就O (n^2) 了

    优化枚举d的复杂度

    我们可以搞个0/1数组,在y左边的设为1,右边的设为0

    然后我们查以 y 为中心的是不是个回文串(是回文串说明找不到等差序列)

    然后回文就从y向左和向右存两个hash判断是否一样

    01数组存正的和反的两个hash,然后单点修改——线段树维护hash

    合并 hash[ls]*base^len(rs)+hash[rs]

    提醒——base 要预处理出来,开long long, 反着的hash维护注意

    #include <cstdio>
    #include <iostream>
    #include <cstring>
    using namespace std;
    #define int long long
    #define mid ((l+r)>>1)
    #define ls (p<<1)
    #define rs (p<<1|1)
    
    inline int read(){
    	int x=0,f=1;char ch=getchar();
    	while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    	while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
    	return f*x;
    }
    const int N=40005;
    const int mod=2147483647;
    int T,n,a[N],len;
    int hash1[N],hash2[N];
    int base[N];
    
    void merge(int p,int len) {
        int m=len>>1;
        hash1[p]=(hash1[ls]*base[m]+hash1[rs])%mod;
        hash2[p]=(hash2[ls]+hash2[rs]*base[len-m])%mod;
    }
    
    void modify(int l,int r,int v,int p) {
        if(l==r) {hash1[p]=hash2[p]=1;return;}
        if(v<=mid) modify(l,mid,v,ls);
        if(v>mid) modify(mid+1,r,v,rs);
        merge(p,r-l+1);
    }
    
    int query1(int L,int R,int l,int r,int p) {
        if(L>R) return 0;
        if(L==l&&r==R) return hash1[p];
        if(R<=mid) return query1(L,R,l,mid,ls);
        else if(L>mid) return query1(L,R,mid+1,r,rs);
        else return (query1(L,mid,l,mid,ls)*base[R-mid]+query1(mid+1,R,mid+1,r,rs))%mod;
    }
    int query2(int L,int R,int l,int r,int p) {
        if(L>R) return 0;
        if(L==l&&r==R) return hash2[p];
        if(R<=mid) return query2(L,R,l,mid,ls);
        else if(L>mid) return query2(L,R,mid+1,r,rs);
        else return (query2(L,mid,l,mid,ls)+query2(mid+1,R,mid+1,r,rs)*base[mid-L+1])%mod;
    }
    
    void clear() {
        memset(hash1,0,sizeof(hash1));
        memset(hash2,0,sizeof(hash2));
    }
    signed main() {
        T=read();
        base[1]=3;
        for(int i=2;i<=10000;i++) base[i]=(base[i-1]*3)%mod;
        while(T--) {
            clear();
            n=read();
            for(int i=1;i<=n;i++) a[i]=read();
            bool flag=0;
            for(int i=1;i<=n;i++) {
                len=min(a[i]-1,n-a[i]);
                if(query1(a[i]-len,a[i]-1,1,n,1)!=query2(a[i]+1,a[i]+len,1,n,1)) {
                    flag=1;break;
                }
                modify(1,n,a[i],1);
            }
            puts(flag?"Y":"N");
        }
        return 0;
    }
    

    啊另解https://www.luogu.com.cn/user/56672

  • 相关阅读:
    深入 HBase 架构解析(2)
    [HEOI2012]朋友圈
    图论常用概念整理
    [COGS2175][SDOI2012]象棋-二分图最大权匹配
    KMP算法
    数据结构部分整理
    最小费用最大流学习笔记
    动态开点线段树
    Splay 模板
    C++ P1164 小A点菜
  • 原文地址:https://www.cnblogs.com/ke-xin/p/13531505.html
Copyright © 2020-2023  润新知