Description
有 N 个严格递增的非负整数 a 1 , a 2 , … , a N ( 0 ≤ a 1 < a 2 < ⋯ < a N ≤ 1 0 18 ) a_1,a_2,…,a_N(0≤a_1<a_2<⋯<a_N≤10^{18}) a1,a2,…,aN(0≤a1<a2<⋯<aN≤1018)。你需要找出 a i + 1 − a i ( 0 ≤ i ≤ N − 1 ) a_{i+1}−a_i(0≤i≤N−1) ai+1−ai(0≤i≤N−1)里的最大的值。
你的程序不能直接读入这个整数序列,但是你可以通过给定的函数来查询该序列的信息。
定义函数
M
i
n
M
a
x
(
s
,
t
,
&
m
n
,
&
m
x
)
MinMax(s, t, \& mn, \& mx)
MinMax(s,t,&mn,&mx),返回时,变量 mn 将会存储满足
a
i
∈
[
s
,
t
]
a_i∈[s,t]
ai∈[s,t] 中 ai 的最小值,变量 mx 将会存储满足
a
i
∈
[
s
,
t
]
a_i∈[s,t]
ai∈[s,t] ,ai 的最大值。
计分方式
对于所有的测试点,有 2≤N≤100000。
每一个测试点开始测试之前,M 都将被初始化为 0。
子任务 1(30 分):每一次调用 MinMax 都将使 M 加 1。为了获得所有分数,需要满足对于该子任务下的所有测试点,都有 M ≤ N + 1 2 M\leq \frac{N+1}{2} M≤2N+1。
子任务 2(70 分):定义 k 为调用 MinMax 时,区间 [ s , t ] [s,t] [s,t]中的序列中数的数量。每次调用 MinMax,将使 M加上 k + 1 k+1 k+1。如果 M ≤ 3 N M≤3N M≤3N,你将得到 70 分
Solution
对于30分:
显然的,你可以先找出全局的最大值和最小值,再向中间推进来找出a中全部元素,
对于70分:
我们可以先求出答案的下界为:
m
x
−
m
i
n
−
1
\frac{mx-mi}{n-1}
n−1mx−mi
我们考虑这个答案什么情况下会更新,找出mi,mx后,我们先把mi~mx这段值域分成n-1段,如果存在更优的答案,那么这个答案在值域上一定是跨区间的,
所以我们暴力找出每个值域区间中是否有数,有数的话mi,mx又分别是多少即可,
总的K刚好等于3N。
Code
#include "gap.h"
#include <cstdio>
#include <algorithm>
#define fo(i,a,b) for(int i=a;i<=b;++i)
#define fod(i,a,b) for(int i=a;i>=b;--i)
#define efo(i,q) for(int i=A[q];i;i=B[i][0])
#define min(q,w) ((q)>(w)?(w):(q))
#define max(q,w) ((q)<(w)?(w):(q))
using namespace std;
typedef long long LL;
const int N=100500;
const LL INF=1e18;
int read(int &n)
{
char ch=' ';int q=0,w=1;
for(;(ch!='-')&&((ch<'0')||(ch>'9'));ch=getchar());
if(ch=='-')w=-1,ch=getchar();
for(;ch>='0' && ch<='9';ch=getchar())q=q*10+ch-48;n=q*w;return n;
}
int n;
LL ans;
LL doit1()
{
LL r,l;
MinMax(0,INF,&l,&r);
for(int i=2;i<n;i+=2)
{
LL mx,mi;
MinMax(l+1,r-1,&mi,&mx);
ans=max(ans,max(mi-l,r-mx));
l=mi,r=mx;
}
return ans=max(ans,r-l);
}
LL doit2()
{
LL mi,mx,m,fr;
MinMax(0,INF,&fr,&m);
LL la=fr;
ans=(m-fr)/(n-1);
for(LL i=fr,t;i<m;i=la+t,la=mx)
{
t=ans+1;
for(;i+1>t+la;t<<=1);
for(MinMax(i+1LL,la+t,&mi,&mx);mi==-1;t<<=1,MinMax(i+1LL,la+t,&mi,&mx));
ans=max(ans,mi-la);
}
return ans;
}
LL findGap(int T, int n1)
{
if(n1==2)
{
LL mi,mx;
MinMax(0,INF,&mi,&mx);
return mx-mi;
}
n=n1;ans=0;
return (T==1)?doit1():doit2();
}