Ural 2064 Caterpillars

Description

Young gardener didn’t visit his garden for a long time, and now it’s not very pleasant there: n caterpillars have appeared on the ground.

Kirill decided to use this opportunity to have some fun and organized a competition — “caterpillar crawl-race.”

At Kirill’s command all caterpillars start crawling from the ground to the top of a tree. But they get tired pretty fast. After crawling ti cm i-th caterpillar needs to rest for ti minutes. During that time it slides down a bit. Crawling speed of a caterpillar is 1 cm/minute, sliding speed — also 1 cm/minute.

Kirill is very much interested to find out how high on the tree is the leading caterpillar at different moments in time.

Input

First line contains one integer n — the number of caterpillars (1 ≤ n ≤ 106).

Second line contains n integers ti — characteristics of caterpillars ( 1ti109 ).

In the third line there is a number q — number of moments in time, which Kirill finds interesting ( 1q106 ).

Remaining q lines contain one query from Kirill each. A query is described by xi — number of minutes since the start of the competition ( 1xi106 ).

Output

For every query print in a separate line one integer, that describes how high is the highest caterpillar at the given moment of time.

题意

给定 n 只毛毛虫,及 n 个数 ti 。对于每只毛毛虫,它们均从 0 时刻以高度 0 向上攀爬,以 1 cm/min 的速度上爬 ti 分钟,再以 1cm/min 的速度下滑 ti 分钟,再以 1 cm/min 的速度上爬 ti 分钟,如此往复。

之后有 q 个询问,每个询问输入一个 x ,问对每个询问给出 n 只毛毛虫在 x 时刻最高的那只毛毛虫的高度。

分析

此题可进行暴力的预处理。

由于询问的 x 最大为 106 ,因此只需预处理出 [1,106] 区间每个时刻的最高高度。

首先可以确定对于毛毛虫 i ti,3ti,5ti,... 时刻它必定处在最高点,因此暴力处理每只毛毛虫在 ti,3ti,5ti,... 时刻的高度计为 ti ,始终求最大值保存在 ans[ x ] 。

对于其余时刻,可视作最高点向两边的扩展,作二维坐标即斜率为 1-1 。正反向分别扫描,ans[ x ] = max(ans[x], ans[x-1] -1) , ans[ x ] = max(ans[x], ans[x+1] - 1)。

需要注意的是,对于 106 时刻这个截止点,必须额外处理,否则可能在边界出错。

此处不得不提及神奇的 ios::sync_with_stdio(0); 否则会被卡时间。

代码

#include<bits/stdc++.h>
using namespace std;
const int N = 1e6;
int n, q, t[N+10], ans[N+10];
void deal()
{
    for(int i=1, j;i<=n;++i)
    {
        if(t[i] == t[i-1])  continue;
        for(j=t[i];j<=N;j+=2*t[i])
            if(t[i] > ans[j])   ans[j] = t[i];
        ans[N] = max(ans[N], t[i] - (j-N));
    }
    for(int i=1;i<=N;++i)   ans[i] = max(ans[i],ans[i-1]-1);
    for(int i=N;i;--i)  ans[i] = max(ans[i],ans[i+1]-1);
}
int main()
{
    ios::sync_with_stdio(0);
    cin>>n;
    for(int i=1;i<=n;i++)
        cin>>t[i];
    sort(t+1, t+n+1);
    deal();
    cin>>q;
    for(int i=1,x;i<=q;i++)
    {
        cin>>x;
        cout<<ans[x]<<endl;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值