ARC179C 题解
Description
有一个黑板和一个长度为
有两种操作
+ i j
:擦去
? i j
:查询
Solution
经过 +
操作后,留下的数一定是 ?
询问保证每一次 +
都合法。
我们不能能通过询问得到任何具体的值,只能知道两个元素的相对大小关系,考虑如何利用大小关系去保证 +
操作前的局面都形如:存在一些数
设当前最大的数为
若
若
若
下面的问题就是如何在有限的交互次数内维护最大值和最小值。交互次数限制为
可以先把初始数组 +
后,二分插入得到的
Code
#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
#define mod 998244353
#define N 2010
#define pb emplace_back
#define szi sizeof(int)
#define il inline
int n,p[N],t[N],nw,ll,rr,mm;
il int cmp(int i,int j){ //比较操作
int x; printf("? %d %d\n",i,j),fflush(stdout);
scanf("%d",&x); return x;
}
il int add(int i,int j){ //加法操作
int x; printf("+ %d %d\n",i,j),fflush(stdout);
scanf("%d",&x); return x;
}
il void rpl(){
puts("!"),fflush(stdout); return ;
}
il void msort(int l,int r){ //我手写归并排序了,如果要写简单一点可以直接用 stable_sort,这个函数是基于归并排序实现的
if(l==r) return ;
int mid=l+r>>1,pl=l,pr=mid+1,tot=l-1;
msort(l,mid),msort(mid+1,r);
while(pl<=mid||pr<=r){
if(pr>r){t[++tot]=p[pl++];continue;}
if(pl>mid){t[++tot]=p[pr++];continue;}
if(cmp(p[pl],p[pr])) t[++tot]=p[pl++];
else t[++tot]=p[pr++];
}
for(int i=l;i<=r;++i) p[i]=t[i];
return ;
}
signed main(){
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
scanf("%d",&n);
for(int i=1;i<=n;++i) p[i]=i;
msort(1,n);
for(int i=1;i<n;++i){
nw=add(p[i],p[n]); ll=i+1,rr=n-1;
while(ll<=rr){ //二分插入位置
mm=ll+rr>>1;
if(cmp(nw,p[mm])) rr=mm-1;
else ll=mm+1;
}
for(int j=n;j>ll;--j) p[j]=p[j-1];
p[ll]=nw;
}
rpl();
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话