zoukankan      html  css  js  c++  java
  • 暑假D5 [国家集训队]等差子序列(字符串hash)

    题目描述

    给一个1到N的排列{Ai},询问是否存在

    1p1<p2<p3<p4<p5<<pLenN(Len3)

    使得Ap1,Ap2,Ap3,,ApLen是一个等差序列。

    输入格式:

    输入的第一行包含一个整数T,表示组数。

    下接T组数据,每组第一行一个整数N,每组第二行为一个1到N的排列,数字两两之间用空格隔开。

    输出格式:

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

    说明

    对于5%的数据,N<=100

    对于30%的数据,N<=1000

    对于100%的数据,N<=10000,T<=7

    题解:

    排列:每个数出现且仅出现一次。

    考虑从左到右枚举等差中项b(数值),在在b左边的数状态记为0,b右边的数状态记为1,。

    考虑如果没有等差数列,那么b+k和b-k在同侧,即同为1或0,可以构成回文串。

    对于回文串的判断,可以用数值hash,正反做一遍即可。

    现在考虑枚举下一个等差中项时,如何利用现在的状态。

    可以用线段树存下正反hash值,每次枚举下一个就单点修改,判断就是区间查询。

    区间合并就是  val左*base^(右区间长度)+val右;

    查询的合并要对查询右边界和右区间边界取min

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    
    #define ull unsigned long long
    const int maxn=100005;
    const ull base=1000007;
    int T,n;
    int num1,num2,root1,root2;
    int a[maxn],a_pos,a_l,a_r;
    ull b[maxn];
    struct tree{
        ull val;
        int ls,rs;
    }t1[maxn<<2],t2[maxn<<2];
    
    void update1(int rt,int len){
        t1[rt].val=t1[t1[rt].ls].val*b[len]+t1[t1[rt].rs].val;
    }
    
    void build1(int &rt,int l,int r){
        rt=++num1;
        if(l==r){
            t1[rt].val=1;
            return ;
        }
        int mid=(l+r)>>1;
        build1(t1[rt].ls,l,mid);
        build1(t1[rt].rs,mid+1,r);
        update1(rt,r-mid);
    }
    
    void update2(int rt,int len){
        t2[rt].val=t2[t2[rt].ls].val*b[len]+t2[t2[rt].rs].val;
    }
    
    void build2(int &rt,int l,int r){
        rt=++num2;
        if(l==r){
            t2[rt].val=1;
            return ;
        }
        int mid=(l+r)>>1;
        build2(t2[rt].ls,l,mid);
        build2(t2[rt].rs,mid+1,r);
        update2(rt,r-mid);
    }
    
    void modify1(int rt,int l,int r){
        if(l==r){
            t1[rt].val=0;
            return ;
        }
        int mid=(l+r)>>1;
        if(a_pos<=mid) modify1(t1[rt].ls,l,mid);
        else modify1(t1[rt].rs,mid+1,r);
        update1(rt,r-mid);
    }
    
    void modify2(int rt,int l,int r){
        if(l==r){
            t2[rt].val=0;
            return ;
        }
        int mid=(l+r)>>1;
        if(a_pos<=mid) modify2(t2[rt].ls,l,mid);
        else modify2(t2[rt].rs,mid+1,r);
        update2(rt,r-mid);
    }
    
    ull querry1(int rt,int l,int r){
        if(a_l<=l&&r<=a_r) return t1[rt].val;
        int mid=(l+r)>>1;
        if(a_r<=mid) return querry1(t1[rt].ls,l,mid);
        else if(a_l>mid) return querry1(t1[rt].rs,mid+1,r);
        else return querry1(t1[rt].ls,l,mid)*b[min(a_r,r)-mid]+querry1(t1[rt].rs,mid+1,r);
    }
    
    ull querry2(int rt,int l,int r){
        if(a_l<=l&&r<=a_r) return t2[rt].val;
        int mid=(l+r)>>1;
        if(a_r<=mid) return querry2(t2[rt].ls,l,mid);
        else if(a_l>mid) return querry2(t2[rt].rs,mid+1,r);
        else return querry2(t2[rt].ls,l,mid)*b[min(a_r,r)-mid]+querry2(t2[rt].rs,mid+1,r);
    }
    
    void nice(){
        num1=num2=root1=root2=0;
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        build1(root1,1,n);
        build2(root2,1,n);
        for(int i=2;i<n;i++){
            a_pos=a[i-1];
            modify1(root1,1,n);
            a_pos=n-a[i-1]+1;
            modify2(root2,1,n);
            ull ret1,ret2;
            int len=min(a[i]-1,n-a[i]);
            if(!len) continue;
            a_r=a[i]-1;a_l=a[i]-len;
            ret1=querry1(root1,1,n);
            a_r=n-a[i];a_l=a_r-len+1;
            ret2=querry2(root2,1,n);
            if(ret1!=ret2) {printf("Y
    ");return ;}
        }
        printf("N
    ");
    }
    
    int main(){
        b[0]=1;
        for(int i=1;i<=100000;i++) b[i]=b[i-1]*base;
        scanf("%d",&T);
        while(T--) nice();
    }
    View Code
  • 相关阅读:
    Asp.net 动态添加Meta标签
    【转】在SharePoint Server 2010中更改“我的网站”
    SPQuery DateTime 类型查询
    Asp.net Web Application 打开 SharePoint 2010 Site 错误 The Web application at could not be found
    How To Create SharePoint 2010 Site Collection In Its Own DB
    C# 文件打印
    面试题 java集合
    《深入理解Java虚拟机》(六)堆内存使用分析,垃圾收集器 GC 日志解读
    《深入理解Java虚拟机》(五)JVM调优
    《深入理解Java虚拟机》(四)虚拟机性能监控与故障处理工具
  • 原文地址:https://www.cnblogs.com/sto324/p/11185587.html
Copyright © 2011-2022 走看看