ARC179C 题解

Description

有一个黑板和一个长度为 n 的数组 A,以及一个正数 R,保证 |Ai|R,|i=1nAi|R,但你并不知道 A 数组和 R 的具体值。初始时黑板上按顺序写着 Xi=Ai(1in)

有两种操作

+ i j:擦去 Xi,Xj 并将 Xi+Xj 写到黑板上,返回 Xi+Xj 这个数是第几个被写上去的数,要求满足 |Xi+Xj|R

? i j:查询 Xi<Xj 是否成立。

n1000,需要在 25000 次操作内使黑板上只剩下一个数 i=1nAi


Solution

经过 n1 次合法的 + 操作后,留下的数一定是 i=1nAi,所以问题在于如何利用 ? 询问保证每一次 + 都合法。

我们不能能通过询问得到任何具体的值,只能知道两个元素的相对大小关系,考虑如何利用大小关系去保证 |Xi+Xj|R。每一次 + 操作前的局面都形如:存在一些数 Xi 且满足所有的 |Xi|R|Xi|R。可以发现,若每次选择最大的数和最小的数相加,绝对值一定不会超过 R

设当前最大的数为 mx,最小的数为 mn,口胡一下证明:

mx<0,那么当前所有数都是负数,所有数的和的绝对值 等于 所有数绝对值的和,因此其中任意两数的绝对值的和都小于等于所有数和的绝对值,因此 R

mn0mx,那么 |mx+mn|max(|mx|,|mn|)R

mn>0 ,则当前所有数都是正数,和所有数都是负数的证明差不多。

下面的问题就是如何在有限的交互次数内维护最大值和最小值。交互次数限制为 25000n1000,观察到 25000 大约是 2nlog2n

可以先把初始数组 A 排序,这里排序使用归并排序,这部分比较次数是 O(nlogn)。然后每次 + 后,二分插入得到的 Xi+Xj,插入次数是 O(n),每次二分是 O(logn),所以这部分的交互次数也是 O(nlogn),总交互次数大约是 2nlog2n ,可以通过本题。


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;
}

posted @   Wonder_Fish  阅读(38)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
点击右上角即可分享
微信分享提示