zoukankan      html  css  js  c++  java
  • LOJ #10121 与众不同 (RMQ+二分)

    题目大意 :给你一个整数序列,定义一个合法子串为子串内所有数互不相同,会有很多询问,求区间$[L,R]$内最长连续合法子串长度

    一道思维不错的$RMQ$题,NOIP要是考这种题可能会考挂一片

    预处理出$f_{i}$数组表示以i结尾的最长子串的起始位置,需要一个辅助$last$数组,表示某个数上一次出现的位置

    那么$f_{i}=max(f_{i-1},last[a_{i}]+1)$

    再$RMQ$预处理出区间内任意一个点结尾的最长子串长度

    对于一个询问$[L,R]$,并不能直接用$RMQ$求出答案,因为有一些在$[L,R]$结尾的最长子串的起始位置可能超出$L$

    然后发现$f_{i}$数组是递增的,所以对于一个询问,二分出一个位置,这个位置结尾的最长子串的左端点,是最后一个左端点超出$L$的位置

    显然,答案要么是二分出的位置$k$到$L$的距离,或者是在$k+1$到$R$之间结尾的最长子串长度

    时间$O(nlogn+mlogn)$

     1 #include <vector>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <algorithm>
     5 #define N 200010
     6 #define M 2001000
     7 #define maxn 1000000
     8 #define inf 0x3f3f3f3f
     9 using namespace std;
    10 
    11 int n,m;
    12 int gint()
    13 {
    14     int ret=0,fh=1;char c=getchar();
    15     while(c<'0'||c>'9'){if(c=='-')fh=-1;c=getchar();}
    16     while(c>='0'&&c<='9'){ret=ret*10+c-'0';c=getchar();}
    17     return ret*fh;
    18 }
    19 
    20 int a[N],ma[N][20],la[M],f[N],lg[N];
    21 int query(int x,int y){
    22     if(x>y) return 0;
    23     int len=y-x+1;
    24     return max(ma[x][lg[len]],ma[y-(1<<lg[len])+1][lg[len]]);
    25 }
    26 
    27 int main()
    28 {
    29     scanf("%d%d",&n,&m);
    30     for(int i=1;i<=n;i++)
    31         scanf("%d",&a[i]);
    32     lg[1]=0;
    33     for(int i=2;i<=n;i++)
    34         lg[i]=lg[i>>1]+1;
    35     for(int i=1;i<=n;i++)
    36         if(!la[a[i]+maxn]){
    37             f[i]=max(f[i-1],1);
    38             la[a[i]+maxn]=i;
    39         }else{
    40             f[i]=max(f[i-1],la[a[i]+maxn]+1);
    41             la[a[i]+maxn]=i;
    42         }
    43     for(int i=1;i<=n;i++) ma[i][0]=i-f[i]+1; 
    44     for(int j=1;j<=lg[n];j++)
    45         for(int i=1;i+(1<<j)-1<=n;i++)
    46         ma[i][j]=max(ma[i][j-1],ma[i+(1<<(j-1))][j-1]);
    47     int x,y;
    48     for(int i=1;i<=m;i++)
    49     {
    50         scanf("%d%d",&x,&y);
    51         x++,y++;
    52         int l=x,r=y,ans=x;
    53         while(l<=r){
    54             int mid=(l+r)>>1;
    55             if(f[mid]<x) ans=mid,l=mid+1;
    56             else r=mid-1;
    57         }
    58         printf("%d
    ",max(ans-x+1,query(ans+1,y)));
    59     }
    60     return 0;
    61 }
  • 相关阅读:
    android模拟器中文乱码
    Broadcast Receviewer
    Spring XML配置里的Bean自动装配
    Spring中的Bean配置
    Spring第一个helloWorld
    MyBatis向数据库中批量插入数据
    MyBatis联合查询和使用association 进行分步式查询
    MyBatis编写映射文件实现增删改操作 附说明及代码
    MyBatis全局配置文件MyBatis-config.xml代码
    MyBatis全局配置文件mybatis-config.xml
  • 原文地址:https://www.cnblogs.com/guapisolo/p/9864897.html
Copyright © 2011-2022 走看看