题目描述
传送门
题解
人生第一道交互题!!!
子任务1:要求查询的次数不超过
n+12
每次查询得到数列的最小值和最大值,然后将询问的区间左右端点同是向内缩小1,继续查询,除了最后一次询问,剩下的询问每次可以得到两个数值,那么我们一定可以在
n+12
次询问内得到每一个数的值。
子任务2:定义 k 为调用 MinMax 时,区间
[s,t]
中的序列中数的数量。每次调用 MinMax,将使 M 加上
k+1
。对于每一个测试点,如果
M≤3N
,你将得到 70 分,否则将得到
60MN+1√−1
先花费
n+1
的代价得到数列中的最大值
l
和最小值
然后将
[l+1,r−1]
均分成
n−2
个权值区间。那么有两种情况。
第一种情况:
n−2
个区间中每个区间都有数,那么每个区间有且仅有一个数,我们可以用
n−2
次询问,花费
n+n−2
得到所有的数,然后统计答案,
第二种情况:存在区间中一个数也没有,那么答案一定会大于均分的区间长度,所有我们不关心每个区间中具体的数,只要考虑是区间最值的且相邻的数,然后更新答案,不要忘记统计最初最大值最小值的贡献,花费与询问的次数与第一种情况是一样的。
代码
#include "gap.h"
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const long long inf=1e18;
long long findGap(int T,int N)
{
long long ans=0;
if (T==1) {
long long mn1,mx1; MinMax(0,inf,&mn1,&mx1);
if (N==1) ans=0;
int tmp=N-2; if (tmp==0) ans=max(ans,mx1-mn1);
while (tmp>0) {
long long mn,mx;
if (mn1+1<=mx1-1) MinMax(mn1+1,mx1-1,&mn,&mx);
else break;
ans=max(ans,max(mn-mn1,mx1-mx));
if (tmp==2) ans=max(ans,mx-mn);
if (mn==mx) tmp--;
else tmp-=2;
mn1=mn; mx1=mx;
}
return ans;
}
if (T==2) {
long long l,r; MinMax(0,inf,&l,&r);
if (N==2||N==1) return r-l;
long long len=(r-l-1)/(N-2)+1; long long last=l;
long long s=l+1,t;
for (int i=1;i<=N-2;i++) {
t=min(s+len-1,r-1);
if (s>t) break;
long long mn,mx; MinMax(s,t,&mn,&mx);
if (mn!=-1) {
ans=max(ans,mn-last);
last=mx;
}
s=t+1;
}
ans=max(ans,r-last);
return ans;
}
}