隆冬将至,几天后跳蚤国便会迎来寒冬,这对于以血肉之躯和飞机搏斗的跳蚤们来说并不是件好事……然而在悠悠历史岁月中,跳蚤国早已有了应对严寒的应急措施方案!
在跳蚤国王的带领下,跳蚤们准备启动天路热能塔 —— 红米 note7(红米 note7 为发烧而生)。这座热能塔高耸入云,直接穿出大气层从太空中直接吸收太阳光,垂直向下将热能送往跳蚤国各个角落。热能塔的制造工艺巧夺天工,被誉为“带来温暖的天路”。
但是跳晚们为了让跳蚤们都因为天气寒冷赖在被子里不肯起床,在热能塔启动后一定会歇斯底里地进攻。跳蚤国高级间谍的情报显示,跳晚国计划将发射
n
台三星 note7 向热能塔发起进攻。进攻将会按一定顺序进行,其中第
为了防止热能塔被炸毁,跳蚤国王特地派尛焱轟(一种新型交通工具,运载能力是小火车的三次幂)运送来了跳蚤们刚研制出不久的新型材料 —— Nokia1050。跳蚤们将会把 Nokia1050 装在热能塔上的某一连续的高度区间上以抵挡进攻。
现在,跳蚤国王想在热能塔受损程度和材料消耗量之间进行取舍。所以对于每个
2≤k≤n
,跳蚤国王想知道整个攻击过程中如果想让 Nokia1050 在某一时段至少挡住连续
k
次攻击,那么安装 Nokia1050 的高度区间的长度至少是多少。其中,若高度区间为
事实上,间谍的消息也不见得会多么靠谱,所以跳蚤国王仅想知道一个不那么准确的答案。具体来说:
如果对于每个
k
你输出的答案
输入格式
第一行一个正整数
n
,保证
第二行
n
个正整数
输出格式
输出
n−1
行,其中第
k−1
行表示至少抵挡连续
k
次攻击时所需的最短高度区间长度。(
因为十分重要所以说两遍,如果对于每个
k
你输出的答案
样例一
input
4 1 7 5 2
output
2 5 6
explanation
当 k=2 时,最优高度区间为 [5,7] ;
当 k=3 时,最优高度区间为 [2,7] ;
当 k=4 时,最优高度区间为 [1,7] 。
注意
k=2
时不能选择高度区间
[1,2]
,虽然能够拦截下第
1
次和第
样例二
input
10 26 723 970 13 422 968 875 329 234 983
output
93 546 639 734 749 957 957 957 970
explanation
样例输出给出的为准确答案,注意下面的输出也是可接受的:
93 540 630 730 740 960 960 960 970
样例三
见样例数据下载。
限制与约定
测试点编号 | n 的规模 | 特殊限制 |
---|---|---|
1 | ai≤100 | |
2 | 无 | |
3 | ||
4 | n≤1000 | |
5 | ||
6 | n≤105 | 每个 ai 均是从 [1,106] 中独立选取的均匀随机整数 |
7 | ||
8 | 无 | |
9 | ||
10 |
对于所有数据,保证 1≤ai≤106 。
时间限制: 1s
空间限制: 256MB
后记
最后跳蚤国保住了热能塔,并且跳蚤国王发现,进入隆冬之后跳晚国的轰炸次数变得越来越少了。原来,不适应在严寒中作战的跳晚国士兵惧怕寒冷变得越来越晚起床了。
“是时候展开反攻了!”
题目大意:给定一个序列, ans[K] 表示 MIN[i,j]长度为K[i,j]中最大值−[i,j]中最小值 ,求出ans[2..n],注意答案有5%波动范围。
我果然是太弱了,比赛的时候只会骗分。官方题解
总体来说这个idea真的不错,我一直再往随机化等具有不确定性的算法上考虑,但实际上5%的波动范围真正的作用是使得答案合法取值得以减少。
随着区间长度的递增,答案显然是单增的(因为最大值随区间长度不降,最小值随区间长度不增),而“相对误差不超过5%,则算作正确”为我们提供了便利,对于某一个答案我们可以找到一个区间使得这个区间中答案都为这个数但是仍保证合法。
我们考虑枚举答案然后在它的可接受区间内更新答案,这样的话我们每次用两个队列和头尾指针来扫一遍整个区间,若是当前头尾指针间的最大值-最小值大于当前枚举的答案就考虑将头指针前移来把最大值和最小值不断弹出直到可以接受,然后更新答案就好了。
而我们显然是不能枚举
106
中答案的,考虑到波动范围为5%,所以我们只枚举
1.05x
的答案就好了,因为这些权值的可接受区间是准确的,那么对应到区间上来说就能保证答案都合法了。
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define INF 2147483647
using namespace std;
const int N=100100;
int n,mx1,mx2,a[N],ans[N];
int q1[N],h1,t1;
int q2[N],h2,t2;
int main()
{
scanf("%d",&n);mx1=INF;
for (int i=1;i<=n;++i)
{
scanf("%d",a+i);
mx1=min(mx1,a[i]);
mx2=max(mx2,a[i]);
}
memset(ans,127,sizeof(ans));
for (int now=0;now<=mx2-mx1+1000000;now=max(now+1,(int)(now*1.05)))
{
h1=h2=1;q1[t1=1]=q2[t2=1]=1;
for (int j=1,i=2;i<=n;++i)
{
while(h1<=t1&&a[q1[t1]]<a[i])--t1;
while(h2<=t2&&a[q2[t2]]>a[i])--t2;
q1[++t1]=i;q2[++t2]=i;
while(a[q1[h1]]-a[q2[h2]]>now)
{
if(q1[h1]==j)++h1;
if(q2[h2]==j)++h2;
++j;
}
ans[i-j+1]=min(ans[i-j+1],a[q1[h1]]-a[q2[h2]]);
}
}
for (int i=n-1;i>=2;--i)ans[i]=min(ans[i],ans[i+1]);
for (int i=2;i<=n;++i)printf("%d\n",ans[i]);
return 0;
}
总结:
1、什么元素有特殊性就要优先想一想能不能从这个方面入手解决问题。