• bzoj2124 等差子序列(hash+线段树)


    2124: 等差子序列

    Time Limit: 3 Sec  Memory Limit: 259 MB
    Submit: 719  Solved: 261
    [Submit][Status][Discuss]

    Description

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

    Input

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

    Output

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

    Sample Input

    2
    3
    1 3 2
    3
    3 2 1

    Sample Output

    N
    Y

    HINT

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

    Source

     

    【思路】

             转化+hash+线段树。

             首先需要明确的一点:A是一个1..n的排列。

             其次将出现情况统计为01字符串分别表示该数字目前为止是否出现,因此对于一个数字当前没有出现以后一定会出现。例如对于{5,2,1,4,3,6}且已经扫到了4,则有01状态为110010,可以看出如果有一对数字以4为中心分别为01则一定有等差数列。又因为非0即1的性质,所以问题可以转化为两个字串是否相等的问题,对应到例子中即s(2,3)是否等于s(6,5),如果相等则必无等差数列反之则必有一个或多个等差数列。

             线段树维护hash,[区间查询单点修改],O(logn)的查询时间,O(logn)的维护时间,总时间为O(nlogn)。

             注:求Hash对应一个区间查询。

    【代码】

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<iostream>
     4 #define FOR(a,b,c) for(int a=(b);a<=(c);a++)
     5 using namespace std;
     6 
     7 typedef long long LL;
     8 const int maxn = 10000+10; 
     9 const int MOD = 100000007;
    10 
    11 int read() {
    12     char c=getchar();
    13     while(!isdigit(c)) c=getchar();
    14     int x=0;
    15     while(isdigit(c)) {
    16         x=x*10+c-'0';
    17         c=getchar();
    18     }
    19     return x;
    20 }
    21 
    22 int n;
    23 int a[maxn],xp[maxn];
    24 
    25 LL sumv[4*maxn][2];
    26 int v;
    27 void update(int u,int L,int R) {
    28     int lc=u<<1,rc=lc+1;
    29     if(L==R) {
    30         sumv[u][0]=sumv[u][1]=1;
    31     }
    32     else {
    33         int M=L+(R-L)/2;
    34         if(v<=M) update(lc,L,M);
    35         else update(rc,M+1,R);
    36         sumv[u][0]=(sumv[rc][0]+xp[R-M]*sumv[lc][0]%MOD)%MOD;
    37         sumv[u][1]=(sumv[lc][1]+xp[M-L+1]*sumv[rc][1]%MOD)%MOD;
    38     }
    39 }
    40 LL query(int node,int l,int r,int a,int b,int x){
    41     int lc=node<<1,rc=lc+1;
    42     if(l==a&&r==b)return sumv[node][x];
    43     int m=(l+r)>>1;
    44     LL left=0,right=0;
    45     if(m<b)right=query(rc,m+1,r,max(m+1,a),b,x);
    46     if(a<=m)left=query(lc,l,m,a,min(m,b),x);
    47     return (x?left+right*xp[max(0,m-a+1)]%MOD:right+left*xp[max(0,b-m)]%MOD)%MOD;
    48 }
    49 int main()
    50 {
    51     freopen("cin.in","r",stdin);
    52     freopen("coutme.out","w",stdout);
    53     int T;
    54     T=read();
    55     while(T--) {
    56         memset(sumv,0,sizeof(sumv));
    57         n=read();
    58         xp[0]=1;    FOR(i,1,n+5) xp[i]=(xp[i-1]<<1)%MOD;
    59         FOR(i,1,n) a[i]=read();
    60         bool f=0;
    61         FOR(i,1,n) {
    62             int x=a[i];
    63             LL lf,rf;
    64             int len=min(x-1,n-x);
    65             if(len&&query(1,1,n,x-len,x-1,0)!=query(1,1,n,x+1,x+len,1)){
    66                 f=1;
    67                 break;
    68             }
    69             v=x;
    70             update(1,1,n);
    71         }
    72         if(f) printf("Y
    ");
    73         else printf("N
    ");
    74     }
    75     return 0;
    76 }
  • 相关阅读:
    自动登录跳板机->开发机
    关于写代码的一下规范
    vscode 配置 GOPATH
    thinkphp6.0 nginx 配置
    vue-cli 3.x 构建项目,webpack没有了?
    Laravel6.0 使用 Jwt-auth 实现多用户接口认证
    怎么在 localhost 下访问多个 Laravel 项目,通过一个IP访问多个项目(不仅仅是改变端口哦)
    laravel 5.8 实现消息推送
    vs code 设置 保存自动格式化vue代码
    项目开发规范(编码规范、命名规范、安全规范、前端优化、源码提交规范、代码维护规范、产品发布规范)
  • 原文地址:https://www.cnblogs.com/lidaxin/p/4984599.html
Copyright © 2020-2023  润新知