zoukankan      html  css  js  c++  java
  • csu 1553(RMQ+尺取法)

    1553: Good subsequence

    Time Limit: 2 Sec  Memory Limit: 256 MB
    Submit: 794  Solved: 287
    [Submit][Status][Web Board]

    Description

    Give you a sequence of n numbers, and a number k you should find the max length of Good subsequence. Good subsequence is a continuous subsequence of the given sequence and its maximum value - minimum value<=k. For example n=5, k=2, the sequence ={5, 4, 2, 3, 1}. The answer is 3, the good subsequence are {4, 2, 3} or {2, 3, 1}.

    Input

    There are several test cases.
    Each test case contains two line. the first line are two numbers indicates n and k (1<=n<=10,000, 1<=k<=1,000,000,000). The second line give the sequence of n numbers a[i] (1<=i<=n, 1<=a[i]<=1,000,000,000).
    The input will finish with the end of file.

    Output

    For each the case, output one integer indicates the answer.

    Sample Input

    5 2
    5 4 2 3 1
    1 1
    1

    Sample Output

    3
    1


    题意:在区间内找一段长度最大的子区间满足子区间的最大值 - 子区间的最小值 <=k ,输出最大值。
    题解:尺取法扫一遍就可以得到了,区间最大最小用RMQ或者线段树都可以。
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    using namespace std;
    #define N 10010
    
    int a[N];
    int max_dp[N][20];
    int min_dp[N][20];
    
    void init_MAX_RMQ(int n){
        for(int i=1;i<=n;i++) max_dp[i][0]=a[i];
        for(int j=1;(1<<j)<=n;j++){
            for(int i=1;i<=n-(1<<j)+1;i++){
                max_dp[i][j] = max(max_dp[i][j-1],max_dp[i+(1<<(j-1))][j-1]);
            }
        }
    }
    int MAX_RMQ(int a,int b){
        int k = (int)(log(b-a+1.0)/log(2.0));
        return max(max_dp[a][k],max_dp[b-(1<<k)+1][k]);
    }
    void init_MIN_RMQ(int n){
        for(int i=1;i<=n;i++) min_dp[i][0]=a[i];
        for(int j=1;(1<<j)<=n;j++){
            for(int i=1;i<=n-(1<<j)+1;i++){
                min_dp[i][j] = min(min_dp[i][j-1],min_dp[i+(1<<(j-1))][j-1]);
            }
        }
    }
    int MIN_RMQ(int a,int b){
        int k = (int)(log(b-a+1.0)/log(2.0));
        return min(min_dp[a][k],min_dp[b-(1<<k)+1][k]);
    }
    int main()
    {
        int n,k;
        while(scanf("%d%d",&n,&k)!=EOF){
            for(int i=1;i<=n;i++){
                scanf("%d",&a[i]);
            }
            init_MAX_RMQ(n);
            init_MIN_RMQ(n);
            int MAX = -1;
            int maxv =a[1], minv = a[1];
            int l = 1,r = 1;
            while(l<=n){
                while(r<=n){
                    maxv = MAX_RMQ(l,r);
                    minv = MIN_RMQ(l,r);
                    if(maxv-minv>k) break;
                    MAX = max(r-l+1,MAX);
                    r++;
                }
                l++;
                maxv = MAX_RMQ(l,r);
                minv = MIN_RMQ(l,r);
            }
            printf("%d
    ",MAX);
        }
        return 0;
    }
  • 相关阅读:
    Windows CMD中 find命令(字符串查找)
    网络地址转换静态NAT
    网络地址转换静态NAT
    Android 的暗示 hint 用法
    Android 的暗示 hint 用法
    SQL Server 扩展事件
    SQL Server 扩展事件
    SqlServer中Exists的使用
    SqlServer中Exists的使用
    数据库还原,System.Data.SqlClient.SqlError: 因为数据库正在使用,所以无法获得对数据库的独占访问权。
  • 原文地址:https://www.cnblogs.com/liyinggang/p/5793036.html
Copyright © 2011-2022 走看看