[UOJ#206. 【APIO2016】Gap]有趣的交互
这是一道有趣的交互题.
uoj206
有 $N$ 个严格递增的非负整数 $a_1, a_2, \dots, a_N$($0 \leq a_1 < a_2 < \cdots < a_N \leq 10^{18}$)。你需要找出 $a_{i + 1} - a_i$($0 \leq i \leq N - 1$)里的最大的值。
你的程序不能直接读入这个整数序列,但是你可以通过给定的函数来查询该序列的信息。关于查询函数的细节,请根据你所使用的语言,参考下面的实现细节部分。
你需要实现一个函数,该函数返回 $a_{i + 1} - a_i$($0 \leq i \leq N - 1$)中的最大值。
实现细节
本题只支持 C/C++/Pascal。C/C++
你需要包含头文件 gap.h。 你需要实现一个函数 findGap(T, N),该函数接受下面的参数,并返回一个 long long 类型的整数:- $T$:子任务的编号($1$ 或者 $2$)
- $N$:序列的长度
Pascal
你需要使用单元 graderhelperlib。 你需要实现一个函数 findGap(T, N),该函数接受下面的参数,并返回一个 Int64 类型的整数:- $T$:子任务的编号($1$ 或者 $2$)(Integer 类型)
- $N$:序列的长度(LongInt 类型)
样例一
C/C++
考虑 $N = 4, a_1 = 2, a_2 = 3, a_3 = 6, a_4 = 8$。 则答案应该是 $3$,可以通过下面的几组对 MinMax 的询问获得:- 调用 MinMax(1, 2, &mn, &mx),则 mn 和 mx 皆返回 $2$。
- 调用 MinMax(3, 7, &mn, &mx),则 mn 返回 $3$,mx 返回 $6$。
- 调用 MinMax(8, 9, &mn, &mx),则 mn 和 mx 皆返回 $8$。
Pascal
考虑 $N = 4, a_1 = 2, a_2 = 3, a_3 = 6, a_4 = 8$。 则答案应该是 $3$,可以通过下面的几组对 MinMax 的询问获得:- 调用 MinMax(1, 2, mn, mx),则 mn 和 mx 皆返回 $2$。
- 调用 MinMax(3, 7, mn, mx),则 mn 返回 $3$,mx 返回 $6$。
- 调用 MinMax(8, 9, mn, mx),则 mn 和 mx 皆返回 $8$。
样例评测方式
样例测评系统从标准输入中读入两行。第一行包含两个整数,子任务编号 $T$,和序列长度 $N$。第二行包含 $N$ 个严格递增的非负整数。然后该程序会向标准输出中写入两行,第一行为 findGap 的返回值,第二行为花费 $M$ 的值。 下面的输入描述了上面的样例:2 4 2 3 6 8
限制与约定
对于所有的测试点,有 $2 \leq N \leq 100000$。 每一个测试点开始测试之前,$M$ 都将被初始化为 $0$。 子任务 1(30 分):每一次调用 MinMax 都将使 $M$ 加 $1$。为了获得所有分数,需要满足对于该子任务下的所有测试点,都有 $M \leq \frac{N + 1}{2}$。 子任务 2(70 分):定义 $k$ 为调用 MinMax 时,区间 $[s, t]$ 中的序列中数的数量。每次调用 MinMax,将使 $M$ 加上 $k + 1$。对于每一个测试点,如果 $M \leq 3N$,你将得到 70 分,否则将得到 $\frac{60}{\sqrt{M/N + 1} - 1}$ 分。你的该子任务的得分是其下所有测试点中的最低分。任务一
由于可以调用(n+1)/2次,那么意味着每次调用一定要新得2个数.直接从[min+1,max-1]继续调用就可以了.任务二
这次调用不只和次数相关,还和调用区间内包含数有关.考虑对于一个[l,R]中包含n个数,那么意味着答案至少为$\lceil \frac{max-min}{N-1} \rceil $,.我们将这个[L,R]区间分成n-1块,这样的话如果有更大的答案意味着一定是跨块的.我们每次一个块一个块查询,用上一次出现的最大值和这一次中的最小值更新答案. 考虑开始一次n个数,查询次数n-1+1次,一个块一格块的扫恰好n个数.刚好满足题意.#include "gap.h"
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
using namespace std;
typedef long long ll;
const ll inf = 1e18;
const int maxn = 1e5+5;
ll a[maxn];
long long findGap(int ty, int n)
{
if(ty==1) {
int ss = (n+1)>>1;
a[0] = -1; a[n+1] = inf+1;
for(int i=1;i<=ss;i++) {
MinMax(a[i-1]+1,a[n-i+2]-1,&a[i],&a[n-i+1]);
}
ll ans = 0;
for(int i=1;i<n;i++) ans = max(ans,a[i+1]-a[i]);
return ans;
} else {
ll L,R;
MinMax(0,inf,&L,&R);
ll gap = (R-L+n-2)/(n-1);
ll ans = gap; ll las=-1;
for(ll i=L;i<=R;i+=gap+1) {
ll mi,mx;
MinMax(i,min(R,i+gap),&mi,&mx);
if(las!=-1&&mi!=-1) ans = max(ans,mi-las);
if(mx!=-1) las = mx;
}
return ans;
}
return 0;
}

浙公网安备 33010602011771号