【题目描述】
注意,本题内存限制为 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 ",cnt[i]);break; } } } return 0; }