D. Fixed Point Guessing

题目:D. Fixed Point Guessing

考点:思维,二分答案

题意:本题是一个交互题,求在不超过 15 15 15 次讯问中得出未被交换的值。现有 [ 1   . . . n ] [1\ ...n] [1 ...n] n n n 个值,有 n − 1 2 \frac{n-1}{2} 2n1 对被交换的值, n n n 为奇数且不超过 1 0 4 10^4 104

思路:可以很清楚的从 15 15 15 次询问这一关键点出发,会发现 ⌈ l o g 2 1 0 4 ⌉ = 14 \lceil log_{2}^{10^4}\rceil=14 log2104=14,所以一定会是二分答案求解问题。给定一个子数组 [ a l , . . . , a r ] [al,...,ar] [al,...,ar],计算一下有多少个 a i a_i ai 使 l ≤ a i ≤ r l≤ai≤r lair。如果这个数是奇数,那么这个子数组就包含未被交换的点,否则就不包含。

证明:每交换一对值,则对子数组的影响是 0 0 0 或者 2 2 2,假设 a x a_x ax [ l , r ] [l,r] [l,r] 的范围内, a y a_y ay 不在 [ l , r ] [l,r] [l,r] 的范围内,交换 a x a_x ax a y a_y ay [ l , r ] [l,r] [l,r] 子数组的记数影响为 0 0 0。假设 a x a_x ax [ l , r ] [l,r] [l,r] 的范围内, a y a_y ay 也在 [ l , r ] [l,r] [l,r] 的范围内,交换 a x a_x ax a y a_y ay [ l , r ] [l,r] [l,r] 子数组的记数影响为 2 2 2

#include<stdio.h>

int main(){
	int t;
	scanf("%d",&t);
	while(t --) {
		int n;
		scanf("%d",&n);
		int l = 1,r = n;
		while(l < r) {
			int mid = (l + r) >> 1;
			printf("? %d %d\n",l,mid);
			fflush(stdout);
			int L = 0;
			for(int i=l;i<=mid;i++) {
				int a;
				scanf("%d",&a);
				if(a >= l && a <= mid) L ++;
			}
			if(L % 2) r = mid;
			else l = mid + 1;
		}
		printf("! %d\n",l);
		fflush(stdout);
	} 
	return 0;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值