专栏文章
题解:P14134 【MX-X22-T5】「TPOI-4E」Get MiN? Get MeX!
P14134题解参与者 3已保存评论 2
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 2 条
- 当前快照
- 1 份
- 快照标识符
- @minq4zp1
- 此快照首次捕获于
- 2025/12/02 06:31 3 个月前
- 此快照最后确认于
- 2025/12/02 06:31 3 个月前
先把序列分成前后两半,那么显然它们问出来的答案是一样的,不妨记为 。
那么显然一边存在 的所有数,而另一边有 。不妨设左边是前者,右边是后者。
可以发现,在左边的集合里任取一个子集,问出来的答案都不超过 。在右边的集合里任取一个子集,问出来的答案都不小于 。且如果把某一边的集合拆成两个,都最多只有其中一个满足问出来恰好等于 。
于是我们把左边的集合拆成两半,问其中一个。把右边的集合拆成两半,问其中一个。
如果问出来存在一个值不等于 ,那么我们就可以确定包含 的集合是左边还是右边。往这个方向递归下去即可。
如果问出来两个都是 ,那么答案只会在这两个询问的集合中。以这两个集合往下递归即可。
最后会剩下两个大小为 的集合,问一下第二种询问即可确定。
询问次数显然是 ,多的一次是开始要确定最初的 。
赛时好像没观察全,但是也通过了。
CPPint solve(std::vector<int>A){
if(A.size()==1)return A[0];
int sz=A.size();
std::vector<int>l,r;
rep(i,0,sz/2-1)l.pb(A[i]);
rep(i,sz/2,sz-1)r.pb(A[i]);
int X=ask1(r);
if(X==1)return solve(r);
else return solve(l);
}
int solve(int k,std::vector<int>l,std::vector<int>r){
if(l.size()==1||r.size()==1){
if(l.size()==1){
int X=ask2(l[0]);
if(X==-1)return l[0];
return solve(r);
}
else{
int X=ask2(r[0]);
if(X==-1)return r[0];
return solve(l);
}
}
std::vector<int>lL,lr,rl,rr;
int szl=l.size(),szr=r.size();
rep(i,0,(szl+1)/2-1)lL.pb(l[i]);
rep(i,(szl+1)/2,szl-1)lr.pb(l[i]);
rep(i,0,(szr+1)/2-1)rl.pb(r[i]);
rep(i,(szr+1)/2,szr-1)rr.pb(r[i]);
int X=ask1(lL),Y=ask1(rl);
if(X<k)return solve(X,lL,lr);
if(Y<k)return solve(Y,rl,rr);
std::vector<int>A,B;
if(X==k)A=lL;else A=lr;
if(Y==k)B=rl;else B=rr;
return solve(k,A,B);
}
void solve(){
int n;read(n);
if(n==1){std::cout<<"! 1"<<std::endl;return;}
std::vector<int>l,r;
rep(i,1,n/2)l.pb(i);
rep(i,n/2+1,n)r.pb(i);
int ans=solve(ask1(l),l,r);
std::cout<<"! "<<ans<<std::endl;
}
相关推荐
评论
共 2 条评论,欢迎与作者交流。
正在加载评论...