P5208-[WC2019] I 君的商店【交互,二分】

正题

题目链接:https://www.luogu.com.cn/problem/P5208


题目大意

有一个长度为\(n\)\(01\)序列\(a\),你知道里面有奇数个\(1\)还是偶数个\(1\)。你每次可以选择两个下标集合\(S/T\)询问集合\(S\)和集合\(T\)位置的数字和哪个更大。

交互库只会告诉你\(S\leq T\)或者\(S\geq T\)

要求在所有询问集合大小之和不超过 \(500100\) 的情况下得到整个\(a\)序列。

\(1\leq n\leq 10^5\)


解题思路

注意到数据中有一个点保证了\(a\)序列单调,我们先假设为单调不升。

此时有\(a_1=1\),那么我们考虑二分,对于一个位置\(mid\),我们判是否\(a_{mid}+a_{mid+1}\leq 1\),如果是,那么说明\(a_{mid+1}=0\),否则\(a_{mid}+a_{mid+1}\geq 1\)就说明了\(a_{mid}=1\)

这样我们同样每次能过缩小一半,但是最后会剩下两个数字,我们用奇偶性去判断。

那么对于一般的情况,我们考虑也去构造一个单调不升的序列,两个数字比不出东西,我们考虑拿三个数字去比较,假设我们现在有一个\(a\leq b\)

我们拿\(a+b\)\(c\)去比较:

  • \(a+b\leq c\),那么有\(a=0\)
  • \(a+b\geq c\),那么有\(b\geq c\),我们把\(b\)加入队列,这样加入队列的都是单调不升的。

code

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e5+10;
int p[N],A[2],B[2];
int query(int *S,int nS,int *T,int nT);
void find_price(int task_id, int n, int k, int ans[]) {
	if(n==1){ans[0]=1;return;}
	if(task_id==3||n==2){
		A[0]=0;B[0]=n-1;
		if(!query(A,1,B,1))
			for(int i=1;i<=n;i++)p[i]=i-1;
		else 
			for(int i=1;i<=n;i++)p[i]=n-i;
		int l=1,r=n-1;
		while(l<r){
			int mid=(l+r+1)>>1;
			A[0]=p[mid];A[1]=p[mid+1];B[0]=p[1];
			if(query(A,2,B,1))
				r=mid-1;
			else l=mid;
		}
		ans[p[l+1]]=(l&1)^k;
		for(int i=1;i<=l;i++)ans[p[i]]=1;
	}
	else{
		int x=0,y=1,tot=0;
		for(int i=2;i<n;i++){
			int z=i;A[0]=y;B[0]=z;//y>=z
			if(query(A,1,B,1))swap(y,z);
			A[0]=x;B[0]=y;B[1]=z;
			if(query(A,1,B,2)){
				p[++tot]=x;
				x=y;y=z;
			}
			else ans[z]=0;
		}
		A[0]=x;B[0]=y;
		if(query(A,1,B,1))p[++tot]=y;
		else p[++tot]=x,swap(x,y);
		for(int i=1;i<tot-i+1;i++)swap(p[i],p[tot-i+1]);
		int l=1,r=tot-1;
		while(l<r){
			int mid=(l+r+1)>>1;
			A[0]=p[mid];A[1]=p[mid+1];B[0]=p[1];
			if(query(A,2,B,1))
				r=mid-1;
			else l=mid;
		}
		for(int i=1;i<=l;i++)ans[p[i]]=1;
		y=p[l+1];A[0]=x;B[0]=y;//x>=y
		if(query(A,1,B,1))swap(x,y);
		A[0]=x;A[1]=y;B[0]=p[1];
		if(query(A,2,B,1))ans[y]=0;
		else ans[x]=1,l++,x=y;
		ans[x]=(l&1)^k;
	}
	return;
}
posted @ 2022-07-11 20:14  QuantAsk  阅读(38)  评论(0编辑  收藏  举报