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\n",MAX);
    }
    return 0;
}
时间: 2024-11-03 16:02:53

csu 1553(RMQ+尺取法)的相关文章

[ACM] CSU 1553 Good subsequence(尺取法)

题目地址:http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1553 给定n的数的序列,求最长连续区间满足区间内的数最大值与最小值的差<=k (尺取法) const int maxn=10010; int num[maxn]; int n,k; int MIN,MAX; int main() { while(scanf("%d%d",&n,&k)!=EOF) { for(int i=1;i<=n;i++) sc

POJ3162 Walking Race(树形DP+尺取法+单调队列)

题目大概是给一棵n个结点边带权的树,记结点i到其他结点最远距离为d[i],问d数组构成的这个序列中满足其中最大值与最小值的差不超过m的连续子序列最长是多长. 各个结点到其他结点的最远距离可以用树形DP解决,HDU2196. 而那个最长的连续子序列可以用单调队列求..搞了挺久看了解法体会了下..简单来说就是尺取法,用两个指针[i,j]表示区间,j不停+1往前移动,然后用两个单调队列分别同时更新区间最小值和最大值,再看两个队列队首的最值差是否大于m,是的话出队并调整i值,最后用j-i+1更新答案.

luogu 1712 区间(线段树+尺取法)

题意:给出n个区间,求选择一些区间,使得一个点被覆盖的次数超过m次,最小的花费.花费指的是选择的区间中最大长度减去最小长度. 坐标值这么大,n比较小,显然需要离散化,需要一个技巧,把区间转化为半开半闭区间,然后线段树的每一个节点表示一个半开半闭区间. 接着我们注意到需要求最小的花费,且这个花费只与选择的区间集合中的最大长度和最小长度有关. 这意味着如果最大长度和最小长度一定,我们显然是需要把中间长度的区间尽量的选择进去使答案不会变的更劣. 不妨把区间按长度排序,枚举每个最小长度区间,然后最大区间

poj 3320 Jessica&#39;s Reading Problem(尺取法+map/hash)

题目:http://poj.org/problem?id=3320 题意:给定N个元素的数组,找出最短的一段区间使得区间里面的元素种类等于整个数组的元素种类. 分析:暴力枚举区间的起点x,然后找到最小的y,使得区间[x,y]满足条件,x向有移位后变成x',现在的y'肯定不至于在y的左边.存状态的话map和hash都可以. map代码: #include <iostream> #include <set> #include <map> #include <cstdi

hihocoder-1483区间价值 (二分+尺取法)

题目链接: 区间价值 给定n个数A1...An,小Ho想了解AL..AR中有多少对元素值相同.小Ho把这个数目定义为区间[L,R]的价值,用v[L,R]表示. 例如1 1 1 2 2这五个数所组成的区间的价值为4. 现在小Ho想知道在所有的的v[L,R](1 <= L <= R <= n)中,第k小的值是多少. Input 第一行一个数T(T<=10),表示数据组数. 对于每一组数据: 第一行两个数n,k(1<=n<=200,000,1<=k<=n*(n+1

【转】毛虫算法&mdash;&mdash;尺取法

转自http://www.myexception.cn/program/1839999.html 妹子满分~~~~ 毛毛虫算法--尺取法 有这么一类问题,需要在给的一组数据中找到不大于某一个上限的"最优连续子序列" 于是就有了这样一种方法,找这个子序列的过程很像毛毛虫爬行方式,我管它叫毛毛虫算法,比较流行的叫法是"尺取法". 喏,就像图里的妹纸一样~ 还是举个栗子: Poj3061 给长度为n的数组和一个整数m,求总和不小于m的连续子序列的最小长度 输入 n = 1

51nod1127(尺取法)

题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1127 题意:中文题诶- 思路:尺取法 维护一个队列,若当前队首的元素在后面出现了,那么我们就将其删除,若当前队列里含有26个字母,我们就记录其size. 取所有size里面的最小值就是我们要的答案... 代码: 1 #include <iostream> 2 #include <stdio.h> 3 #include <string>

BestCoder Round #86 二,三题题解(尺取法)

第一题太水,跳过了. NanoApe Loves Sequence题目描述:退役狗 NanoApe 滚回去学文化课啦! 在数学课上,NanoApe 心痒痒又玩起了数列.他在纸上随便写了一个长度为 nnn 的数列,他又根据心情随便删了一个数,这样他得到了一个新的数列,然后他计算出了所有相邻两数的差的绝对值的最大值. 他当然知道这个最大值会随着他删了的数改变而改变,所以他想知道假如全部数被删除的概率是相等的话,差的绝对值的最大值的期望是多少. 输入描述 第一行为一个正整数 T,表示数据组数. 每组数

POJ 3320 尺取法,Hash,map标记

1.POJ 3320 2.链接:http://poj.org/problem?id=3320 3.总结:尺取法,Hash,map标记 看书复习,p页书,一页有一个知识点,连续看求最少多少页看完所有知识点 必须说,STL够屌.. #include<iostream> #include<cstring> #include<cmath> #include<queue> #include<algorithm> #include<cstdio>