zoukankan      html  css  js  c++  java
  • 牛客练习赛85 C 哲学家的沉思 尺取 单调递增子序列 倍增

    传送门

    题意:

    每次询问一个区间,求这个区间最长单调递增子序列的长度

    题解:

    赛时想到了尺取预处理,从当前的点开始第一个高度大于它的点的位置

    然后就没有然后了

    赛后看题解,用的方法是倍增,具体方法是,维护一个数组st[j][i]

    代表从j点开始,跳$2^i$次能到哪个点

    这样的话每次询问复杂度就到了log n

    AC代码(非本人原创):

    #include<bits/stdc++.h>
    using namespace std;
    
    int a[100005],rr[100005],st[100005][20];
    int main()
    {
        int i,j,n,q,l,r,ans;
        scanf("%d%d",&n,&q);
        for(i=1;i<=n;i++)scanf("%d",&a[i]);
        st[n][0]=rr[n]=n+1;
        for(i=n-1;i>=1;i--)
        {
            for(j=i+1;j!=n+1&&a[j]<=a[i];j=rr[j]);
            rr[i]=st[i][0]=j;
        }
        for(i=1;i<=17;i++)
        {
            for(j=1;j<=n;j++)
            {
                if(st[j][i-1]>n)st[j][i]=1e9;
                else st[j][i]=st[st[j][i-1]][i-1];
            }
        }
        while(q--)
        {
            scanf("%d%d",&l,&r),ans=0;
            for(i=17;i>=0;i--)if(st[l][i]<=r)l=st[l][i],ans|=(1<<i);
            printf("%d
    ",ans+1);
        }
    }

    另外,有人说是CF1516D的弱化版,条件从两两互质变成了左边的最大

  • 相关阅读:
    线段树优化dp(elect选择)
    gdb调试
    无参装饰器
    3.23作业
    3.22周末作业
    函数对象与闭包函数
    3.20作业
    3.19作业
    名称空间与作用域
    函数参数的使用
  • 原文地址:https://www.cnblogs.com/isakovsky/p/14932895.html
Copyright © 2011-2022 走看看