DTOJ #2927. Around the world

梦想的初衷 提交于 2019-11-27 18:04:48

【题目描述】

注意,本题内存限制为 24 MiB

通过几年的努力,Byteasar最终拿到了飞行员驾驶证。为了庆祝这一事实,他打算买一架飞机并且绕Byteotia星球赤道飞行一圈。

但不幸的是赤道非常长所以需要中途加几次油。现在已知赤道上面所有飞机场,所有飞机从飞机场起飞降落也可以加油。因为买飞机是个十分重大的决定,Byteasar决定寻求你的帮助。他将会让你模拟不同的飞行路线。自然这些飞机一次能走的航程是不同的。

对于每次模拟,他想要知道最少需要降落多少次(包括最后一次)。需要注意的是起点可以任意选取。

【输入格式】

第 $1$ 行有两个正整数 $n$ 和 $s(2 \le n \le 1000000,1 \le s \le 100) $分别代表赤道上面的飞机场个数和询问的航班数。

第 $2$ 行有 $n$ 个正整数 $L_1,L_2,\cdots,L_n (L_1+L_2+\cdots+L_n \le 10^9)$按顺序给出了 $n$ 个相邻机场之间的距离。其中 $L_i$ 是第 $i$ 个与第 $i+1$ 个机场之间的距离,$L_n$ 是第 $n$ 个和第 $1$ 个之间的距离。

第 $3$ 行给出了 $s$ 个正整数 $d_i(1 \le di \le L_1+L_2+...+L_n)$。其中 $d_i$ 代表第 $i$ 个飞机一次能走的航程。

【输出格式】

输出 $s$ 行每行一个整数代表最小降落次数或者一个字符串 $NIE$ 代表不能到达。

【数据范围与提示】

样例输入
6 4
2 2 1 3 3 1
3 2 4 11

样例输出
4
NIE
3
2

【题解】

由于是环,考虑破环成链。首先不合法路线很好判断。

考虑贪心,显然从任意点开始,能往后跳多远就跳多远一定是最优的。同理,对于一个点,从前面离它最远的点跳过来也一定是最优的。

对于每个起点(前 $n$ 个点),我们强制令其第一步必须跳到后 $n$ 个点,这样一定是合法的。

于是对于后 $n$ 个点,用一个指针从 $1$ 开始往后推,得到每个点前面离它最远的点及来源、路径点数。碰到第一个来源与当前点距离大于 $n$ 的即为答案。

时间效率 $O(ns)$,理论空间最优复杂度 $O(3n)$。

【代码】

#include<bits/stdc++.h>
inline int read ( void )
{
    int x=0;char ch;
    while ( !isdigit(ch=getchar()) ) ;
    for ( x=ch^48;isdigit(ch=getchar()); ) x=(x<<1)+(x<<3)+(ch^48);
    return x;
}
int a[2000010],n,s,nxt[2000010],cnt[2000010],max;
signed main()
{
    n=read();s=read();
    for ( int i=1;i<=n;i++ ) max=std::max(a[i]=a[i+n]=read(),max);
    for ( int i=1;i<=2*n;i++ ) a[i]+=a[i-1];
    for ( int i=1;i<=s;i++ )
    {
        int d=read();
        if ( d<max ) { puts("NIE");continue; }
        for ( int i=1;i<=n;i++ ) nxt[i]=i;
        for ( int i=n+1,j=1;i<=2*n;i++ )
        {
            while ( a[i]-a[j]>d ) j++;
            nxt[i]=nxt[j];cnt[i]=cnt[j]+1;
            if ( i-nxt[i]>=n ) { printf("%d\n",cnt[i]);break; }
        }
    }
    return 0;
}

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!