zoukankan      html  css  js  c++  java
  • bzoj 2124 等差子序列 (线段树维护hash)

    2124: 等差子序列

    Time Limit: 3 Sec  Memory Limit: 259 MB
    Submit: 1922  Solved: 714
    [Submit][Status][Discuss]

    Description

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

    Input

    输入的第一行包含一个整数T,表示组数。
    下接T组数据,每组第一行一个整数N,每组第二行为一个1到N的排列,数字两两之间用空格隔开。
    N<=10000,T<=7
     

    Output

    对于每组数据,如果存在一个等差子序列,则输出一行“Y”,否则输出一行“N”。
     

    Sample Input

    2
    3
    1 3 2
    3
    3 2 1

    Sample Output

    N
    Y
     
    思路:
     
    线段树神仙操作。。完全想不到怎么用线段树写,看了别人题解看了一天才看懂这操作。。
    题目要求存在个数不小于3的等差序列就行了,那么我们只要找到三个数可以组成等差序列就可以了。
    我们先从1-n逐步插入,用01表示插入的状态吗如果插入了就标为1,然后只要找出当前值左右两边是否存在
    距离相等但状态不同的点,如果有的话那么就存在这么一种等差序列,因为状态不同只有一种情况:一个之前
    就已经插入了,一个还没插入,但另一个迟早会插入,所以我们不用管,只要找到这个就可以确定他是等差序列了。
    用线段树维护一下hash就行了。
    线段树维护的操作比较麻烦,主要就是将这个由01组成的序列由二进制转成10进制来保存,每一步都取下模,如果这
    两个数的十进制不同,那他们的二进制肯定也不同。这样就可以判断出答案了。
     
    实现代码;
    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define mid ll m = (l + r) >> 1
    const ll M = 1e5+10;
    const ll md = 1e9+7;
    ll suml[M<<2],sumr[M<<2],a[M],pw[M];
    void pushup(ll l,ll r,ll rt){
        ll len = r - l + 1;
        ll m = len / 2;
        suml[rt] = (suml[rt<<1]*pw[m]+suml[rt<<1|1])%md;
        sumr[rt] = (sumr[rt<<1|1]*pw[len-m]+sumr[rt<<1])%md;
        return ;
    }
    
    void update(ll p,ll l,ll r,ll rt){
        if(l == r){
            suml[rt] = sumr[rt] = 1;
            return ;
        }
        mid;
        if(p <= m) update(p,lson);
        else update(p,rson);
        pushup(l,r,rt);
    }
    
    ll queryl(ll L,ll R,ll l,ll r,ll rt){
        if(L > R) return 0;
        if(L == l&&R == r) return suml[rt];
        mid;
        if(L > m) return queryl(L,R,rson);
        else if(R <= m) return queryl(L,R,lson);
        else return (queryl(L,m,lson)*pw[R-m]+queryl(m+1,R,rson))%md;
    }
    
    ll queryr(ll L,ll R,ll l,ll r,ll rt){
        if(L > R) return 0;
        if(L == l&&R == r) return sumr[rt];
        mid;
        if(L > m) return queryr(L,R,rson);
        else if(R <= m) return queryr(L,R,lson);
        else  return (queryr(L,m,lson)+queryr(m+1,R,rson)*pw[m-L+1])%md;
    }
    
    int main()
    {
        ll t,n;
        ios::sync_with_stdio(0);
        cin.tie(0); cout.tie(0);
        cin>>t;
        pw[1] = 2;
        for(ll i = 2;i <= 100001;i++)
            pw[i] = (pw[i-1]*2)%md;
        while(t--){
            cin>>n;
            memset(suml,0,sizeof(suml));
            memset(sumr,0,sizeof(sumr));
            memset(a,0,sizeof(a));
            ll flag = 1;
            for(ll i = 1;i <= n;i ++) cin>>a[i];
            for(ll i = 1;i <= n;i ++){
                ll len = min(a[i]-1,n-a[i]);
                ll t1 = queryl(a[i]-len,a[i]-1,1,n,1);
                ll t2 = queryr(a[i]+1,a[i]+len,1,n,1);
                if(t1!=t2){
                    flag = 0;break;
                }
                update(a[i],1,n,1);
            }
            if(!flag) cout<<"Y"<<endl;
            else cout<<"N"<<endl;
        }
    }
  • 相关阅读:
    从Go语言编码角度解释实现简易区块链——打造公链
    CSAPP:位操作实现基本运算
    虚拟机Ubuntu系统无法连接网络解决方案
    CSAPP:逆向工程【二进制炸弹】
    分析一套源代码的代码规范和风格并讨论如何改进优化代码
    【Recorder.js+百度语音识别】全栈方案技术细节
    webpack4.0各个击破(5)—— Module篇
    webpack4.0各个击破(4)—— Javascript & splitChunk
    webpack4.0各个击破(3)—— Assets篇
    javascript基础修炼(4)——UMD规范的代码推演
  • 原文地址:https://www.cnblogs.com/kls123/p/8849776.html
Copyright © 2011-2022 走看看