标签:finish xl xm int CF1480C mid Searching CF1479A xr
[CF1479A] Searching Local Minimum - 二分
Description
藏一个排列,\(n \le 10^5\),最多 100 次询问,找到任意一个局部最小值 \(a_i<a_{i+1},a_i<a_{i-1}\)
Solution
先把一些容易判的判掉,比如 \(n\le 100\),\(a_1,a_n\) 之类
类似二分,维护两个端点,每次取中间,看中间这个位置的相邻三个元素是什么大小关系
如果中间最小,运气太好,那么已经找到答案,直接结束
如果中间最大,随便往哪边走
如果是单调的,那么往有减小趋势的那边走
(并不会证明)
#include <bits/stdc++.h>
using namespace std;
int ask(int i)
{
cout << "? " << i << endl;
cout.flush();
int x;
cin >> x;
return x;
}
void finish(int x)
{
cout << "! " << x << endl;
cout.flush();
exit(0);
}
const int N = 100005;
int n, a[N];
void test(int x)
{
if (x == 1 || x == n)
return;
int mid = x;
int xl = ask(mid - 1), xm = ask(mid), xr = ask(mid + 1);
if (xl > xm && xm < xr)
finish(mid);
}
signed main()
{
cin >> n;
if (n == 1)
{
finish(1);
}
if (n <= 100)
{
for (int i = 1; i <= n; i++)
a[i] = ask(i);
finish(min_element(a + 1, a + n + 1) - a);
}
a[1] = ask(1);
a[2] = ask(2);
a[n - 1] = ask(n - 1);
a[n] = ask(n);
if (a[1] < a[2])
finish(1);
if (a[n - 1] > a[n])
finish(n);
int l = 1, r = n;
while (r - l > 3)
{
int mid = (l + r) / 2;
int xl = ask(mid - 1), xm = ask(mid), xr = ask(mid + 1);
if (xl > xm && xm < xr)
finish(mid);
if (xl < xm && xm < xr)
r = mid;
else if (xl > xm && xm > xr)
l = mid;
else
r = mid;
}
for (int i = l; i <= r; i++)
test(i);
throw("...");
}
标签:finish,xl,xm,int,CF1480C,mid,Searching,CF1479A,xr 来源: https://www.cnblogs.com/mollnn/p/14387524.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。