Problem - D - Codeforces (Unofficial mirror by Menci)
第一次写交互题,没看题解一次过(赛后补题)
题目大意:一个长度为 n 的数组包含 1~ n( n 为奇数),选择 ( n - 1)/ 2 个元素对,交换他们的位置,问未被交换的元素是哪个
方法:二分
l = 0,r = n,mid = ( l + r )/2;
_includes = (l ,r)中在范围外的数量
- 左段长度为奇数
- 假设该元素在内,_includes为偶数(可能为0)
- 不在该段内,_includes为奇数
- 左段长度为偶数
- 假设该元素在内,_includes为奇数
- 不在该段内,_includes为偶数(可能为0)
这样我们就很容易用二分写出来了
代码实现
#include<bits/stdc++.h>
#define debug0(x) cout << "debug0: " << x << endl
#define fr(t, i, n) for (int i = t; i < n; i++)
#define first fi
#define second se
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
const int N = 1e4+10;
int a[N];
void solve(){
int n;cin >> n;
int l = 1,r = n;
while(l < r){
int mid = (l+r) >> 1;
cout << "?" << " " << l << " " << mid << endl;//询问
int includes = 0;
for(int i = 0;i < mid-l+1;i ++){
cin >> a[i];
if(a[i] >= l && a[i] <= mid)includes++; //计算_includes
}
int _includes = mid-l+1 - includes;
if((mid-l+1) % 2){ //判断二分
if(_includes % 2 == 0)r = mid;
else l = mid +1;
}else{
if(_includes % 2 == 0)l = mid +1;
else r = mid;
}
}
cout << "!" << " " << l << endl;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int T;cin >> T;
while(T--){
solve();
}
return 0;
}