【线段树】nyoj-备用 2344: 盖伦的告白

2344: 盖伦的告白

时间限制: 1 Sec   内存限制: 128 MB
提交: 44   解决: 16
[ 提交][ 状态][ 讨论版]

题目描述

盖伦和赵信这对基友又在打赌,谁输了就去向卡特琳娜告白。。

这一季中盖伦一如既往的怂。赵信为了帮他一把,故意表现出很厉害的样子,结果成功激活了盖伦的智商。

赵信手中有n张牌,每张牌上面有一个数,这些牌是非递减的。现在盖伦从他手中抽取k张牌,如果盖伦抽取后剩下的牌中相邻两张的差值的最大值最小,就算他赢。

结果当然是盖伦赢了。那么问题来了!

输入

第一行两个正整数n和k。

第二行n个数代表n张牌。

3≤n≤105

1≤k≤n-2

-109≤Ai≤109

输出

输出只有一个数,上述中的最小值。

样例输入

5 1
1 2 4 7 8
8 2
1 2 3 5 8 13 17 18
5 1
1 2 4 6 9

样例输出

3
5
2

题意:有一非递减序列A,要随意抽掉k个数字,剩下n-k个数为序列B,问序列B的相邻元素的差值最大值,最小是多少。
思路:我刚看到这题就想着什么最大值最小化,确实是啊,但是不是用二分的;先思考给定的序列为非递减序列,那么相邻的元素之间的差才会更小,如果从中间去掉的话,就会扩大相邻两数之间的差值,所以最优是一次抽掉的k个数是相连的;我们再求剩下的区间的相邻元素差(预处理)的最大值,然后对最大值比较取最小,最后得到的minn就是最小值了;多组数据输入,在这儿wa了好几发;
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

const int N=100005;
const int inf=1000000007;
int a[N];

struct node
{
    int l,r;
    int val;
    int mid()
    {
        return (l+r)>>1;
    }
} tree[N<<2];

void BuildTree(int l,int r,int rt)
{
    tree[rt].l=l,tree[rt].r=r;
    if(l==r)
    {
        tree[rt].val=abs(a[l+1]-a[l]);
        return ;
    }

    int m=tree[rt].mid();
    BuildTree(l,m,rt<<1);
    BuildTree(m+1,r,rt<<1|1);
    tree[rt].val=max(tree[rt<<1].val,tree[rt<<1|1].val);
}

int Query(int l,int r,int rt)
{
    if(tree[rt].l==l&&tree[rt].r==r)
        return tree[rt].val;

    int m=tree[rt].mid();
    if(r<=m) return Query(l,r,rt<<1);
    else if(l>m) return Query(l,r,rt<<1|1);
    else return max(Query(l,m,rt<<1),Query(m+1,r,rt<<1|1));
}

int main()
{
    int n,k;
    while(~scanf("%d%d",&n,&k))
    {

        for(int i=1; i<=n; i++)
            scanf("%d",&a[i]);
        a[n+1]=inf;
        BuildTree(1,n,1);

        int minn=inf;
        for(int i=1; i<=k+1; i++)
        {
            int res=Query(i,i+n-k-1-1,1);
            minn=min(minn,res);
        }
        printf("%d\n",minn);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值