版权声明:本文为蒟蒻所写,神犇转载尽情拍打喂食虐待,如发现任何的辣鸡错误欢迎吐槽! https://blog.csdn.net/HOWARLI/article/details/84866419
Description
有 N 个严格递增的非负整数 。你需要找出 里的最大的值。
你的程序不能直接读入这个整数序列,但是你可以通过给定的函数来查询该序列的信息。
定义函数
,返回时,变量 mn 将会存储满足
中 ai 的最小值,变量 mx 将会存储满足
,ai 的最大值。
计分方式
对于所有的测试点,有 2≤N≤100000。
每一个测试点开始测试之前,M 都将被初始化为 0。
子任务 1(30 分):每一次调用 MinMax 都将使 M 加 1。为了获得所有分数,需要满足对于该子任务下的所有测试点,都有 。
子任务 2(70 分):定义 k 为调用 MinMax 时,区间 中的序列中数的数量。每次调用 MinMax,将使 M加上 。如果 ,你将得到 70 分
Solution
对于30分:
显然的,你可以先找出全局的最大值和最小值,再向中间推进来找出a中全部元素,
对于70分:
我们可以先求出答案的下界为:
我们考虑这个答案什么情况下会更新,找出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();
}