[CF1698D]Fixed Point Guessing

做题时间:2022.6.29

这是一道交互题。评测机生成一个长度为 N(3N104,n) 的序列 a=[1,2,...,n] ,并交换 n12 组互不相同的位置上的数字,最后有且仅有一个数字的位置不变,给出操作完的序列。你可以向评测机询问区间 [l,r] 中的数按升序排列后的结果,询问次数不超过 15 次,最后你要求出这个位置不变的数。

第一行一个整数 t 表示数据组数
每组数据第一行一个整数 N
第二行 N 个整数表示序列 a

二分

可以发现询问次数很少,且 log100015 很接近,可以考虑二分。

每次查找一个 [l,mid] ,想要判断位置不变的数是否在其中分几种情况讨论,如果 [l,mid] 中的其中 k 个数与 [l,mid] 之外的数进行了交换那么 大小[l,mid] 中的数的个数就减去了 k ,而 [l,mid] 内的数两两交换则不变。可以理解为,操作完成后,若 [l,mid] 中的数全部被交换过,那么 大小[l,mid] 内的数要么被交换出去,要么成对留下。因此若 [l,mid] 区间中大小在 [l,mid] 中的数有奇数个,说明位置不变的数就在其中。

#include<iostream>
#include<cstdio>
#include<iomanip>
using namespace std;
const int N=1e4+50;
int a[N],t,n;
void Query(int x,int y)
{
int cnt=0;
cout<<"? "<<x<<" "<<y<<endl;
for(int i=1;i<=y-x+1;i++) cin>>a[i];
fflush(stdout);
}
int main()
{
cin>>t;
while(t--){
cin>>n;
int l=1,r=n;
while(l<r){
int mid=(l+r)>>1;
Query(l,mid);
int cnt=0;
for(int i=1;i<=mid-l+1;i++){
if(a[i]>=l&a[i]<=mid) cnt++;
}
if(cnt%2==0) l=mid+1;
else r=mid;
}
cout<<"! "<<l<<endl;
fflush(stdout);
}
return 0;
}

本文作者:lxzy

本文链接:https://www.cnblogs.com/Unlimited-Chan/p/16456924.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   lxzy  阅读(25)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
💬
评论
📌
收藏
💗
关注
👍
推荐
🚀
回顶
收起
  1. 1 404 not found REOL
404 not found - REOL
00:00 / 00:00
An audio error has occurred.