[APIO2016]Gap

题目:UOJ#206。

题目大意:由于过于冗长,不好解释,所以详见原题。

解题思路:这是一道交互题。

对于第一问,很容易解决。由于数列严格递增,所以不会出现相等的情况。

首先调用MinMax(0,10^18,&l,&r)求出最小值和最大值,然后每次调用MinMax(l+1,r-1,&l,&r)求出次大值、次小值,第三大值、第三小值……

如此调用$lfloor frac{N+1}{2} floor$次,就可以求出整个数组。然后求值即可。

对于第二问,首先仍然是求出最小值min和最大值max。

然后,可以知道[min,max]之间还有N-2个数,那么中间就被分为了N-1份。

根据抽屉原理可知,两数之间的最大间隔至少为$lceil frac{a_N - a_1}{N-1} ceil$,设其为p。

那么我们就将查找区间分为N-1份,每次查找的区间大小都为p(最后一个区间除外),然后每次用当前查询到的最小值减去上次查询到的最大值(跳过-1),得出的答案进行比较,最大的那个就是答案。

由于最大间隔至少为p,所以最大间隔一定在两个不同区间中,因此这样做能得到正确的答案。

m的值:第一次调用N+1,之后N-1次调用,总共包含不超过N个点,所以$mleq N+1+N+N-1$,即$mleq 3N$,符合条件。

然后即可AC。

C++ Code:

#include"gap.h"
#define ll long long
ll p[100005];
ll findGap(int T,int N){
	if(T==1){
		int l=1,r=N;
		ll LL=0,RR=1000000000000000000;
		while(l<=r){
			ll xx,yy;
			MinMax(LL,RR,&xx,&yy);
			p[l++]=xx,p[r--]=yy;
			LL=xx+1,RR=yy-1;
		}
		ll max=0;
		for(int i=1;i<N;++i)
		if(p[i+1]-p[i]>max)max=p[i+1]-p[i];
		return max;
	}else{
		ll xx,yy;
		MinMax(0,1000000000000000000,&xx,&yy);
		ll k=(yy-xx)/(N-1);
		if((yy-xx)%(N-1))++k;
		ll prer=xx,max=0,nowl,nowr;
		for(ll l=xx+1;l<yy;l+=k){
			ll r=l+k-1;
			if(r>yy)r=yy-1;
			MinMax(l,r,&nowl,&nowr);
			if(nowl-prer>max)max=nowl-prer;
			if(nowr!=-1)
			prer=nowr;
		}
		if(yy-prer>max)max=yy-prer;
		return max;
	}
}
原文地址:https://www.cnblogs.com/Mrsrz/p/8150419.html