第四届「帆软杯」东南大学大学生程序设计竞赛(冬季)- 复赛 435/E.分段函数 另一种二分方式

xukuan 2023-03-16 22:47:17 2023-03-16 22:47:35

首先中间那段没啥用,只考虑左右两端就行

那么我们在l,l+1l,l+1r1,rr-1,r中取不为0的值,即为斜率k

二分时,如果fmidfl=k(midl)f_{mid}-f_l=k*(mid-l),说明a[mid,r)a \in [mid,r),否则a[l,mid)a \in [l,mid)

注意:这题存在卡二分次数的问题,所以如果找斜率的时候出现了k和0,直接输出并结束,不然会超次数然后WA;另外找斜率时不要用取max,不然次数也会炸。

#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#define ll long long
using namespace std;

ll T,l,r;

inline ll query(ll l,ll r){
	printf("? %lld %lld\n",l,r); fflush(stdout);
	ll val; scanf("%lld",&val);
	return val/(r-l);
}

inline void answer(ll k,ll b){
	printf("! %lld %lld\n",k,b); fflush(stdout);
}

int main(){
	scanf("%lld",&T);
	while(T--){
		scanf("%lld %lld",&l,&r);
		ll k=query(l,l+1);
		if(k==0) k=query(r-1,r);
		else while(r-l>1){
			ll mid=(l+r)>>1;
			if(query(l,mid)==k) l=mid;
			else r=mid;
		}
		answer(k,l);
	}
	return 0;
}