Soratosorato

CF1945E Binary Search 题解

Sorato·2024-03-21 13:12·32 次阅读

CF1945E Binary Search 题解

CF1945E Binary Search

题目大意#

给定一个 1n 的排列 A(不保证有序),对这个排列用如下代码片段二分,查找 m 的位置。

Copy
int l=1,r=n+1; while(r-l>1) { int mid=(l+r)/2; if(A[mid]<=m) l=mid; else r=mid; } cout<<l;

显然不一定能查找到正确位置,所以在开始查找之前,可以进行至多 2 次操作,每次操作可交换任意两个数的位置,可以保证 2 次操作一定能使答案正确。

Solve#

由于体面说 2 次操作一定能使答案正确,我们不妨大胆地猜测一下:

先对原数列使用上面的代码,进行二分,将二分出来的位置(记为 x)与 m 的位置交换即可。

然后就发现 AC 了。

考虑证明一下正确性:

显然我们最后二分出的 px 一定是 小于等于 m 的。然后考虑分情况讨论:

  • 如果二分过程中 mid,Amidm,那么这样交换肯定是没问题的,因为交换之后不会对 A[mid]<=m 这句话有影响。
  • 如果 mid,Amid=m,那么交换之后 Amid 就等于 px 了,此时 A[mid]<=m 仍然为真,不影响二分端点的变化。

得证。

Code#

Copy
#include<bits/stdc++.h> #pragma GCC optimize(1,2,3,"Ofast","inline") using namespace std; #define int long long inline int read() { short f=1; int x=0; char c=getchar(); while(c<'0'||c>'9') {if(c=='-') f=-1;c=getchar();} while(c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } int t,n,m,a[200010],pos; signed main() { t=read(); for(int i=1;i<=t;i=-~i) { n=read();m=read(); for(int j=1;j<=n;j=-~j) { a[j]=read(); if(a[j]==m) pos=j; } int l=1,r=-~n; while(r-l>1) { int mid=l+r>>1; if(a[mid]<=m) l=mid; else r=mid; } printf("1\n%lld %lld\n",l,pos); } return 0; }
posted @   Sorato  阅读(32)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示
目录