1 条题解
-
0
自动搬运
来自洛谷,原作者为

MoSalah
退役不退学搬运于
2025-08-24 22:37:58,当前版本为作者最后更新于2022-05-02 22:53:36,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
题意
这是一道交互题
首先,在这里感谢出题人让我知道了怎么写交互题。
在 次询问内,你要求出最初的 数组。
询问方式有三种:
-
询问 中有几个不同的值,交互库会返回一个正整数 表示答案。
-
使 。
-
输出答案。
返回的数值 就是
题解
模拟? 分。
数组中每一位往前的最大值就可能是:
画图发现,如果第 位的值为当前数组中最大值,那么询问这个点往后的询问值一定与第 位的询问值相符。那么最后一位的询问值一定与第 位的询问值一样。现在就是要找到这个 位,记录下来。
考虑二分。
在这个数组中二分查询这个 位,首先询问一次 位,如果第 位和第 位相同,那么查找 往前的位置,不然查找 往后的位置,最终查找到开头的位置,那么这位置一定是 。标记后将 清零,那么这个序列中的最大值就是 ,重复操作,直到确定 的位置。
过程在图片里面。

清零之后求 以此类推。好了,这道题就解决了。
代码
#include <bits/stdc++.h> using namespace std; int ans[50005]; int main(){ int t; scanf("%d",&t); while(t--){ int n; scanf("%d",&n); for(int i=n;i>=1;i--){ printf("? 1 %d\n\n",n); fflush(stdout);//刷新缓存 int biao; scanf("%d",&biao); int l=1,r=n; while(l<r){ int mid=(l+r)>>1; int tmp; printf("? 1 %d\n\n",mid); fflush(stdout);//刷新缓存 scanf("%d",&tmp); if(tmp==biao) r=mid; else l=mid+1; } printf("? 2 %d\n\n",r); fflush(stdout);//刷新缓存 ans[r]=i; } printf("!"); for(int i=1;i<=n;i++) printf(" %d",ans[i]); puts("\n"); fflush(stdout);//刷新缓存 } return 0; } -
- 1
信息
- ID
- 7279
- 时间
- 1000ms
- 内存
- 128MiB
- 难度
- 4
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者