• 洛谷P2757 [国家集训队]等差子序列 (hash+线段树)


    题目连接

    这题只要令 $len=3$看是否符合即可。因为是一个 $1$到 $n$的排列,考虑数列中项,那么对于一个数 $x$,令 $k=max(n-x, x-1)$,只要存在 $din(1,k)$,使 $x+d$和 $x-d$位于数 $x$在序列中的位置的异侧即可。进一步分析我们要做的就是从左向右扫一遍序列,每扫过一个数就将其在值域区间上打上标记,对于目前扫到的数 $x$,判断在值域区间上以它为中心的左右长度为 $k$的区域是否对称,如果对称代表在 $[1,n]$范围内所有以它为中项的能与它形成等差数列的一对值都在同侧,不满足,否则满足。判断区间相等问题不难想到hash,用线段树维护即可。

    #include<cstdio>
    #include<cstring>
    #define min(a,b) (a)<(b) ? (a):(b)
    #define ull unsigned long long
    const int maxn = 1e5+50;
    const int p = 998244353;
    
    int T,n;
    int a[maxn];
    ull kk[maxn],hash[2][maxn<<2];
    bool vis;
    
    void pushup(int x,int len){
        int tt = len>>1;
        hash[0][x] = (hash[0][x<<1]*kk[tt]+hash[0][x<<1|1]) % p;
        hash[1][x] = (hash[1][x<<1]+hash[1][x<<1|1]*kk[len-tt]) % p;
    }
    
    void update(int x,int l,int r,int val){
        if(l == r){
            hash[0][x] = hash[1][x] = 1;
            return ;
        }
        int mid = l+r>>1;
        if(val <= mid)  update(x<<1,l,mid,val);
        else    update(x<<1|1,mid+1,r,val);
        pushup(x,r-l+1);
    }
    
    ull query(int x,int l,int r,int ql,int qr,int sta){
        if(ql > qr)     return 0;
        if(ql <= l && qr >= r)  return hash[sta][x];
        int mid = l+r>>1;
        if(qr <= mid)   return query(x<<1,l,mid,ql,qr,sta);
        else if(ql > mid)   return query(x<<1|1,mid+1,r,ql,qr,sta);
        ull dx = kk[qr-mid], dy = 1;
        if(sta)  dx = 1, dy = kk[mid-ql+1];
        return (query(x<<1,l,mid,ql,mid,sta)*dx+query(x<<1|1,mid+1,r,mid+1,qr,sta)*dy) % p;
    }
    
    int main(){
        scanf("%d",&T);  kk[0] = 1;
        for(int i = 1; i < maxn; ++i)   kk[i] = kk[i-1]*3%p;
        while(T--){
            memset(hash,0,sizeof(hash));
            scanf("%d",&n);  vis = 0;
            for(int i = 1; i <= n; ++i)  scanf("%d",&a[i]);
            for(int i = 1; i <= n; ++i){
                int q = min(a[i]-1,n-a[i]);
                if(query(1,1,n,a[i]-q,a[i]-1,0) != query(1,1,n,a[i]+1,a[i]+q,1)){
                    vis = 1;  break;
                }
                update(1,1,n,a[i]);
            }
            puts(vis ? "Y":"N");
        }
        return 0;
    }
    你只有十分努力,才能看上去毫不费力。
  • 相关阅读:
    找东西
    检测内存泄漏
    八月份月度反思
    博客之路
    快速开发~Rafy框架的初步认识
    VS快捷键的简单总结
    web前端使用工具的总结
    直接把数据库中的数据保存在CSV文件中
    AngularJs HTML DOM、AngularJS 事件以及模块的学习(5)
    AngularJS控制器和AngularJS过滤器的学习(3)
  • 原文地址:https://www.cnblogs.com/214txdy/p/14045528.html
Copyright © 2020-2023  润新知