CF1480

CF1480

C 交互,有一个1e5的排列。你可以询问100次每个位置的数是多少,求一个位置,使得左右两边都比它大。0和n+1是无穷大。

赛场上我写了个假二分,是如果a[r] - a[l] < r - l,则其中一定有一个极小值点。反例是单峰,只有极大值点。

赛后又想了个正确的,还是二分,维护一段答案区间,使得这个区间两边的值都比各自的区间边界上的那个值要大。这样区间内一定有一个极小值。每次二分的时候查中间位置的两个数,然后取一边。

 1 #include <bits/stdc++.h>
 2 
 3 const int N = 100010;
 4 
 5 int a[N];
 6 
 7 inline int ask(int x) {
 8     if(a[x]) {
 9         return a[x];
10     }
11     printf("? %d\n", x);
12     fflush(stdout);
13     scanf("%d", &a[x]);
14     return a[x];
15 }
16 
17 int main() {
18     int n;
19     scanf("%d", &n);
20     int l = 1, r = n;
21     a[0] = a[n + 1] = n + 1;
22     while(r - l > 2) {
23         int mid = (l + r) >> 1;
24         if(ask(mid) > ask(mid + 1)) {
25             l = mid + 1;
26         }
27         else {
28             r = mid;
29         }
30     }
31     for(int i = l; i <= r; i++) {
32         if(ask(i) < ask(i + 1) && ask(i) < ask(i - 1)) {
33             printf("! %d\n", i);
34             return 0;
35         }
36     }
37     return -1;
38 }
AC代码

D

posted @ 2021-02-27 00:57  huyufeifei  阅读(6)  评论(0编辑  收藏