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;
}