CF1081F

设这个序列为 a。注意到连续操作 [i,i] 两次所形成的序列要么是 a,要么是除了 ai 都翻转的序列。我们可以多随几次,总能碰到第二种情况,然后就能知道第 i 个数是 0 还是 1 了,然后再还原回去。当然有一个问题就是除开 ai 以外剩下的 01 数量相等,这里我们可以把 [i,i] 改为 [i,i+1],这样每次能得到 ai+ai+1,最后再统计一下就可以了。这样我们就得到了一个期望 8n 次询问的做法。

Code:

#include <bits/stdc++.h>
using namespace std;
#define ff fflush(stdout)
const int N = 305;
int n, k;
int ans[N], a[N];

int ask(int l, int r) {
	printf("? %d %d\n", l, r);
	ff;
	int res; scanf("%d", &res);
	return res;
}

void print() {
	printf("! ");
	for (int i = 1; i <= n; ++i) printf("%d", ans[i]);
}

int work(int l, int r) {
	int res;
	do { res = ask(l, r), res = ask(l, r); } while (res == k);
	int dis = res - (n - k);
	do { res = ask(l, r), res = ask(l, r); } while (res != k);
	return (r - l + 1 + dis) / 2;
}

int main() {
	scanf("%d%d", &n, &k);
	if (n == 2 * k + 1 || n == 2 * k - 1) {
		for (int i = 1; i < n; ++i) a[i] = work(i, i + 1);
		a[n] = 2 * k;
		for (int i = 1; i < n; ++i) a[n] -= a[i];
		for (int i = 1; i < n; ++i) {
			if (i & 1) ans[n] -= a[i];
			else ans[n] += a[i];
		}
		ans[n] = (ans[n] + a[n]) / 2;
		for (int i = n - 1; i; --i) ans[i] = a[i] - ans[i + 1];
	}
	else for (int i = 1; i <= n; ++i) ans[i] = work(i, i);
	print();
	return 0;
}
posted @   Kobe303  阅读(27)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示