CF1479A Searching Local Minimum
题意:
题解:
先说结论:
若l,r满足:
- al−1>al,ar<ar+1a_{l-1}>a_{l},a_{r}<a_{r+1}al−1>al,ar<ar+1
- al,al+1,....,ara_{l},a_{l+1},....,a_{r}al,al+1,....,ar互不相同
则一定又一个满足题目条件的k会出现在区间[l,r]中,这就是我们要找的区间
现在我们开始证明:
利用反证法:假设对于任意k∈[l,r]多不满足要求(即ak<min{ai−1,ai+1}a_{k}<min\{a_{i-1},a_{i+1}\}ak<min{ai−1,ai+1})
因为al−1>ala_{l-1}>a_{l}al−1>al,且l不满足要求,al!=al+1a_{l}!=a_{l+1}al!=al+1,则一定有al>al+1a_{l}>a_{l+1}al>al+1
同理可得:al+1>al+2a_{l+1}>a_{l+2}al+1>al+2,al+2>al+3a_{l+2}>a_{l+3}al+2>al+3,.........,ar−1>ara_{r-1}>a_{r}ar−1>ar
又因为ar+1>ara_{r+1}>a_{r}ar+1>ar,则r满足情况,与假设不符
现在开始用这个结论做题,a0=an+1=+∞a_{0}=a_{n+1}=+∞a0=an+1=+∞,说明区间[l,r]就是符合结论的区间,那么答案也肯定在这里面,现在我们要缩小区间范围,可以二分,二分出一个mid,询问mid和mid+1的值
若amid<amid+1a_{mid}<a_{mid+1}amid<amid+1,说明[l,mid]也是符合结论的,这样缩小范围
若amid>amid+1a_{mid}>a_{mid+1}amid>amid+1,说明[mid+1,r]是符合要求的
这样二分就解决了
代码:
#include <bits/stdc++.h>
#include <unordered_map>
#define debug(a, b) printf("%s = %d\n", a, b);
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
clock_t startTime, endTime;
//Fe~Jozky
const ll INF_ll= 1e18;
const int INF_int= 0x3f3f3f3f;
void read(){};
template <typename _Tp, typename... _Tps> void read(_Tp& x, _Tps&... Ar)
{x= 0;char c= getchar();bool flag= 0;while (c < '0' || c > '9')flag|= (c == '-'), c= getchar();while (c >= '0' && c <= '9')x= (x << 3) + (x << 1) + (c ^ 48), c= getchar();if (flag)x= -x;read(Ar...);
}
template <typename T> inline void write(T x)
{if (x < 0) {x= ~(x - 1);putchar('-');}if (x > 9)write(x / 10);putchar(x % 10 + '0');
}
void rd_test()
{
#ifdef ONLINE_JUDGE
#elsestartTime = clock ();freopen("data.in", "r", stdin);
#endif
}
void Time_test()
{
#ifdef ONLINE_JUDGE
#elseendTime= clock();printf("\nRun Time:%lfs\n", (double)(endTime - startTime) / CLOCKS_PER_SEC);
#endif
}
const int maxn=1e5+9;
int a[maxn];
int main()
{//rd_test();int n;read(n);int l=1,r=n;while(l<r){int mid=l+r>>1;if(a[mid]==0){printf("? %d\n",mid);fflush(stdout);cin>>a[mid];}if(a[mid+1]==0){printf("? %d\n",mid+1);fflush(stdout);cin>>a[mid+1];}if(a[mid]<a[mid+1]){r=mid;}else if(a[mid]>a[mid+1]){l=mid+1;}
// printf("");}printf("! %d\n",l);return 0;//Time_test();
}