LOJ#2569. 「APIO2016」最大差分 分块+交互
比较有趣的交互题.
subtask1:
由于每次调用这个函数可以返回值域中的最大值和最小值,所以可以每次查询出两个元素.
那么每次查到 $x,y$ 后就将查询区间缩小为 $[x+1,y-1]$,这样可以在规定操作次数内解决问题.
subtask2:
这个 subtask 比较困难.
首先,我们发现答案的下界是 $B=\frac{Max-Min}{n-1}$,那么所有在 $B$ 长度内的两个数都不会产生贡献.
考虑将 $[Min,Max]$ 的值域分成 $m$ 块,每块的长度为 $B$,那么有贡献的两个数一定是一个块的最大值和下一块的最小值.
查询总代价为: $n+1+n-1+n \leqslant 3n$.
code:
#include "gap.h"
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#define pb push_back
#define ll long long
using namespace std;
const ll inf=1000000000000000002ll;
vector<ll>a;
void MinMax(ll l,ll r,ll &x,ll &y) {
printf("? %lld %lld\n",l,r);
fflush(stdout);
scanf("%lld%lld",&x,&y);
fflush(stdin);
}
ll sol1(int len) {
ll l=-inf,r=inf;
int tot=0;
while(l<=r) {
ll mi,ma;
MinMax(l,r,mi,ma);
if(mi>=0) a.pb(mi),++tot;
if(ma>mi) a.pb(ma),++tot;
l=mi+1,r=ma-1;
if(tot==len) break;
}
sort(a.begin(),a.end());
ll ans=0;
for(int i=1;i<a.size();++i) {
ans=max(ans,a[i]-a[i-1]);
}
return ans;
}
ll sol2(int len) {
ll s,t,p;
MinMax(0,inf,s,t);
p=(t-s)/(len-1);
ll ans=p;
ll pre=s;
for(ll i=s+1;i<=t;i+=p+1) {
ll a,b;
MinMax(i,i+p,a,b);
if(a!=-1) ans=max(ans,a-pre),pre=b;
}
return ans;
}
long long findGap(int T, int N)
{
if(T==1) return sol1(N);
else {
return sol2(N);
}
}
int main() {
int T,n;
scanf("%d%d",&T,&n);
fflush(stdin);
printf("! %lld\n",findGap(T,n));
return 0;
}

浙公网安备 33010602011771号