Loongint 的花篮

Description

Loongint 要和 MM 结婚了。在两人的走进礼堂的红地毯两侧,需要摆一些装饰用的花篮,有一些不同高度的花篮,现在这些花篮被 Loongint 依照自己的美学观念编号为S1, S2, S3 … Sn(两侧的花篮高度一样)。可 Loongint的 MM 对这些花篮的摆放方式有不同的看法,她觉得满足以下条件的花篮摆放才是最好的。如果对于区间[Si, Sj](1 ≤i<j ≤n中任意的花篮都比Si高且比Sj低,那么这个区间称为一个美学区间。对于所有的美学区间,其长度(定义为j−i)都必须小于等于k,如果有长度大于k的美学区间,MM 就会不高兴,Loongint 就会有麻烦…

Input

第一行为m。表示有m组测试数据。
对于每一组:
第一行n,k,分别表示花篮的数量和美学区间的最大长度。
第二行为n个数,分别表示S1, S2, S3 … Sn的值。

Output

如果根本不存在美学区间,输出−1。
如果存在美学区间,那么如果任意区间的长度都小于等于k,那么输出最大的长度,
否则输出最大长度比k大多少(MaxLength − k)。

Sample Input

3
4 2
5 4 3 6
4 1
6 5 4 3
4 2
1 2 3 4

Sample Output

1
-1
1

Hint

对于30%的测试数据,1 ≤ n ≤ 100。
对于60%的测试数据,1 ≤ n ≤ 5555。
对于100%的测试数据,1 ≤ n≤ 100000, 0 < Si ≤ 100000, 1 ≤ m ≤ 3。


这道题需要采用递增栈求出当前坐标递增、递减的最长长度,不过保存坐标比较简单,

保存右边的递增的最大位置,保存左边递减的最小位置。


#include <stdio.h>
#include <string.h>
#define INF 0x7fffffff
const int maxn = 100005;
int a[maxn], y[maxn], l[maxn], r[maxn], x[maxn];
inline int Max ( int a, int b )
{
    return a > b ? a : b;
}
void print ( int n, int a[] )
{
    for ( int i = 0; i < n; i ++ )
        printf ( "%d ", a[i] );
    printf ( "\n" );
}
int main ( )
{
    int T, n, k, top, ans;
    scanf ( "%d", &T );
    while ( T -- )
    {
        memset ( l, 0, sizeof ( l ) );
        memset ( r, 0, sizeof ( r ) );
        memset ( x, 0, sizeof ( x ) );
        scanf ( "%d%d", &n, &k );
        for ( int i = 1; i <= n; i ++ )
            scanf ( "%d", &a[i] );
        a[0] = INF;
        a[n+1] = -INF;  //为第一个赋最大值,为最后一个赋最小值,添加结束条件
        ans = top = 0;
        x[top] = 1;
        y[top] = a[1];
        for ( int i = 2; i <= n+1; i ++ )
        {
            while ( top >= 0 && y[top] >= a[i] )
            {
                r[ x[top] ] = i-1;  //表示x[top]坐标右边最多达到i-1
                top --;
            }
            top ++;
            x[top] = i;
            y[top] = a[i];
        }   //求出右边递增的最大坐标
        top = 0;
        x[top] = n;
        y[top] = a[n];
        for ( int i = n-1; i >= 0; i -- )
        {
            while ( top >= 0 && y[top] <= a[i] )
            {
                l[ x[top] ] = i+1;  //左边坐标最多是i+1,当前坐标不算
                top --;
            }
            top ++;
            x[top] = i;
            y[top] = a[i];
        }   //求出坐标递减的最小坐标
        for ( int i = 1; i <= n; i ++ )
        {
            for ( int j = r[i]; j >= i; j -- )
            //判断此区间中是否有递减坐标小于等于i
            {
                if ( l[j] <= i )
                {
                    ans = Max ( ans, j-i );
                    break ;
                }
            }
            for ( int j = l[i]; j <= i; j ++ )
            {
                if ( r[j] >= i )
                {
                    ans = Max ( ans, i-j );
                    break ;
                }
            }
        }
        if ( ans == 0 )
            ans = -1;
        else if ( ans > k )
            ans = ans-k;
        printf ( "%d\n", ans );
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值