题目:UOJ#206。
题目大意:由于过于冗长,不好解释,所以详见原题。
解题思路:这是一道交互题。
对于第一问,很容易解决。由于数列严格递增,所以不会出现相等的情况。
首先调用MinMax(0,10^18,&l,&r)求出最小值和最大值,然后每次调用MinMax(l+1,r-1,&l,&r)求出次大值、次小值,第三大值、第三小值……
如此调用$\lfloor \frac{N+1}{2}\rfloor$次,就可以求出整个数组。然后求值即可。
对于第二问,首先仍然是求出最小值min和最大值max。
然后,可以知道[min,max]之间还有N-2个数,那么中间就被分为了N-1份。
根据抽屉原理可知,两数之间的最大间隔至少为$\lceil \frac{a_N - a_1}{N-1}\rceil$,设其为p。
那么我们就将查找区间分为N-1份,每次查找的区间大小都为p(最后一个区间除外),然后每次用当前查询到的最小值减去上次查询到的最大值(跳过-1),得出的答案进行比较,最大的那个就是答案。
由于最大间隔至少为p,所以最大间隔一定在两个不同区间中,因此这样做能得到正确的答案。
m的值:第一次调用N+1,之后N-1次调用,总共包含不超过N个点,所以$m\leq N+1+N+N-1$,即$m\leq 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; } }