对于子任务一,要求最多只能查询 n+12
n
+
1
2
次。我们可以从两边向中间逼近,一次确定两个数,这样就能够在规定次数内确定所有的数。数都到手了还不会做?唉,我太弱啦!
对于子任务二,计数器等于查询次数 + 查询到的数,注意计数器最多可以到 3n
3
n
(没读题的我默认最多为 n
n
QAQ)。首先我们总得确定数的范围是吧,这会花费 n+1 次查询。对于中间的,我们把它分成 n−2
n
−
2
个块,然后分别查询。最后的答案就是块与块之间的最小值减去最大值(不要忘了一开始的最小值和最大值)。为什么呢?如果每一块中恰好有一个数,这显然正确,否则答案一定出现在跨过至少一个块的地方,这还是由一个最小值减去最大值得来的,不会是一个块内产生的答案。
参考代码
#include "gap.h"#include <cstdio>#include <cstdlib>#include <cmath>#include <cstring>#include <cassert>#include <cctype>#include <climits>#include <ctime>#include <iostream>#include <algorithm>#include <vector>#include <string>#include <stack>#include <queue>#include <deque>#include <map>#include <set>#include <bitset>#include <list>#include <functional>typedeflonglong LL;
typedefunsignedlonglong ULL;
usingstd::cin;
usingstd::cout;
usingstd::endl;
typedef LL INT_PUT;
INT_PUT readIn()
{
INT_PUT a = 0; bool positive = true;
char ch = getchar();
while (!(ch == '-' || std::isdigit(ch))) ch = getchar();
if (ch == '-') { positive = false; ch = getchar(); }
while (std::isdigit(ch)) { a = a * 10 - (ch - '0'); ch = getchar(); }
return positive ? -a : a;
}
void printOut(INT_PUT x)
{
char buffer[20]; int length = 0;
if (x < 0) putchar('-'); else x = -x;
do buffer[length++] = -(x % 10) + '0'; while (x /= 10);
doputchar(buffer[--length]); while (length);
}
constint maxn = int(1e5) + 5;
int n;
longlong a[maxn];
LL solve1()
{
LL min = 0, max = LL(1e18);
int cntL = 1, cntR = n;
while (cntL <= cntR)
{
MinMax(min, max, a + cntL, a + cntR);
min = a[cntL] + 1;
max = a[cntR] - 1;
cntL++;
cntR--;
}
LL ans = 0;
for (int i = 2; i <= n; i++)
ans = std::max(ans, a[i] - a[i - 1]);
return ans;
}
LL minVal[maxn], maxVal[maxn];
LL solve2()
{
LL min = 0, max = LL(1e18);
MinMax(min, max, &min, &max);
if (n == 2) return max - min;
LL step = (max - min - 1) / (n - 2);
LL cnt = min + 1;
for (int i = 1; i < n - 2; i++)
{
MinMax(cnt, cnt + step - 1, &minVal[i], &maxVal[i]);
cnt += step;
}
MinMax(cnt, max - 1, &minVal[n - 2], &maxVal[n - 2]);
LL ans = 0;
cnt = min;
for (int i = 1; i <= n - 2; i++)
{
if (minVal[i] == -1) continue;
ans = std::max(ans, minVal[i] - cnt);
cnt = maxVal[i];
}
ans = std::max(ans, max - cnt);
return ans;
}
LL findGap(int type, int N)
{
n = N;
if (type == 1) return solve1();
elsereturn solve2();
}
交互题
由于这是第一道交互题,这里总结下交互题怎么做。
交互题大致形式
一般来说是这样哈,反正我也没做过什么交互题。
在我的印象中,大部分题目都是交互库处理的输入,交互库才是老大,因此你的程序不需要写 main 函数,也不需要写输出函数,只需要按题目要求返回交互库的调用,或者告诉交互库你的需求或答案。