【UOJ #206】【APIO2016】Gap

版权声明:本文为蒟蒻所写,神犇转载尽情拍打喂食虐待,如发现任何的辣鸡错误欢迎吐槽! https://blog.csdn.net/HOWARLI/article/details/84866419

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}) 。你需要找出 a i + 1 a i 0 i N 1 a_{i+1}−a_i(0≤i≤N−1) 里的最大的值。

你的程序不能直接读入这个整数序列,但是你可以通过给定的函数来查询该序列的信息。
定义函数 M i n M a x ( s , t , & m n , & m x ) MinMax(s, t, \& mn, \& mx) ,返回时,变量 mn 将会存储满足 a i [ s , t ] a_i∈[s,t] 中 ai 的最小值,变量 mx 将会存储满足 a i [ s , t ] a_i∈[s,t] ,ai 的最大值。

计分方式

对于所有的测试点,有 2≤N≤100000。

每一个测试点开始测试之前,M 都将被初始化为 0。

子任务 1(30 分):每一次调用 MinMax 都将使 M 加 1。为了获得所有分数,需要满足对于该子任务下的所有测试点,都有 M N + 1 2 M\leq \frac{N+1}{2}

子任务 2(70 分):定义 k 为调用 MinMax 时,区间 [ s , t ] [s,t] 中的序列中数的数量。每次调用 MinMax,将使 M加上 k + 1 k+1 。如果 M 3 N M≤3N ,你将得到 70 分

Solution

对于30分:
显然的,你可以先找出全局的最大值和最小值,再向中间推进来找出a中全部元素,

对于70分:
我们可以先求出答案的下界为: m x m i n 1 \frac{mx-mi}{n-1}
我们考虑这个答案什么情况下会更新,找出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();
}

猜你喜欢

转载自blog.csdn.net/HOWARLI/article/details/84866419