NYOJ备用2344 盖伦的告白(线段树||双端队列)
2017-07-31 15:29
417 查看
2344: 盖伦的告白
时间限制: 1 Sec 内存限制: 128 MB提交: 56 解决: 19
[提交][状态][讨论版]
题目描述
盖伦和赵信这对基友又在打赌,谁输了就去向卡特琳娜告白。。这一季中盖伦一如既往的怂。赵信为了帮他一把,故意表现出很厉害的样子,结果成功激活了盖伦的智商。
赵信手中有n张牌,每张牌上面有一个数,这些牌是非递减的。现在盖伦从他手中抽取k张牌,如果盖伦抽取后剩下的牌中相邻两张的
4000
差值的最大值最小,就算他赢。
结果当然是盖伦赢了。那么问题来了!
输入
第一行两个正整数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
链接:传送门
由于题目中给出 这些数字是非递减的,那么从中间删,肯定会产生更大差值所以要考虑从两边删
所以思路就是从两边删除k个元素,取剩下n-k个元素的最值即可,有两种写法
1:线段树O(nlogn)
#include<bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int N=100005;
ll a
,t[N<<2];
void build(ll l,ll r,ll rt)
{
if(l==r)
{
t[rt]=a[l+1]-a[l];
return;
}
ll m=(l+r)>>1;
build(l,m,rt<<1);
build(m+1,r,rt<<1|1);
t[rt]=max(t[rt<<1],t[rt<<1|1]);
}
ll query(ll x,ll y,ll l,ll r,ll rt)
{
if(l>=x&&r<=y)
{
return t[rt];
}
ll m=(l+r)>>1;
if(y<=m)
return query(x,y,l,m,rt<<1);
else if(x>m)
return query(x,y,m+1,r,rt<<1|1);
else
return max(query(x,m,l,m,rt<<1),query(m+1,y,m+1,r,rt<<1|1));
}
int main()
{
ll n,k;
while(~scanf("%lld%lld",&n,&k))
{
mem(t,0);
for(ll i=1;i<=n;i++)
scanf("%lld",&a[i]);
ll len=n-k-1,ans=0x3f3f3f3f;
build(1,n-1,1);
for(ll i=1;i+len<=n;i++)
ans=min(ans,query(i,len+i-1,1,n-1,1));
printf("%lld\n",ans);
}
}2.双端队列 O(n)
#include<bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int N=100010;
int a
,diff
,q
,idx
;
int main()
{
int n,k;
while(~scanf("%d%d",&n,&k))
{
for(int i=1;i<=n;i++)
{
scanf("%d",a+i);
if(i>1)diff[i-1]=a[i]-a[i-1];
}
int head=0,rear=0;
for(int i=1;i<=n-k-1;i++)
{
while(head<rear&&q[rear-1]<=diff[i])
rear--;
q[rear]=diff[i];
idx[rear++]=i;
}
int ans=q[head];
for(int i=n-k;i<=n-1;i++)
{
while(head<rear&&q[rear-1]<=diff[i])
rear--;
q[rear]=diff[i];
idx[rear++]=i;
while(head<rear&&idx[head]<=i-n+k+1)head++;
ans=min(ans,q[head]);
}
printf("%d\n",ans);
}
return 0;
}
相关文章推荐
- 【线段树】nyoj-备用 2344: 盖伦的告白
- NYOJ-备用2344 盖伦的告白(线段树,区间最大值)
- NYOJ 1128 手速(双端队列)
- CF 6E 线段树 or Multiset or 双端队列维护区间最值
- nyoj1117 鸡蛋队列 (双端队列,deque)
- nyoj754 黑心医生 结构体优先队列
- NYOJ116 士兵杀敌(二)(线段树区单点更新,区间求和,zkw线段树)
- NYOJ-568/1012//UVA-12299RMQ with Shifts,线段树单点更新+区间查询
- [2017纪中11-6]奇怪的队列 树状数组+二分/线段树
- NYOJ 士兵杀敌(三)(线段树,树状数组)
- nyoj108 士兵杀敌(一) (线段树)
- Java高级技术第四章——Java容器类Queue之体验双端队列ArrayQueue设计之妙
- 双端队列
- 双端队列(deque)的应用
- java数据结构之LinkedDeque(用链表实现的双端(即头尾两个哨兵节点)双向(node里两个指向)队列)
- 2014上海区域赛 I题 Defeat the Enemy 离线读入 在线更新 线段树套优先队列
- [ NYOJ - 119] 士兵杀敌(三)(线段树)
- STL之双端队列(deque)
- NYOJ 55 懒省事的小明 【优先队列】
- nyoj-119 士兵杀敌(三) 线段树