赞
踩
A题比较简单就不说了。
B题也比较简单,md,但是写法有问题。
bool cmp(node a,node b)
{
return a.t<b.t;//点前不同,点后同。
}
首先判断 a [ 1 ] a[1] a[1] 和 a [ n ] a[n] a[n] 是不是局部最小值,假如是则输出。
否则: a [ 1 ] a[1] a[1] 到 a [ 2 ] a[2] a[2] 呈下降趋势, a [ n ] a[n] a[n] 到 a [ n − 1 ] a[n - 1] a[n−1] 呈下降趋势,则 2 2 2 ~ n − 1 n-1 n−1中必定存在拐点,即局部最小值。
这时候发现一个性质:
当一个区间 [ l , r ] [l, r] [l,r]左右皆呈向中间下降的趋势的时候,区间一定存在局部最小值。
不难想到在该区间中(不包含端点)任取一点 p o s pos pos,该点要么是局部最小值,否则它一定存在一个相邻点比它小,假设 a [ p o s − 1 ] < a [ p o s ] a[pos - 1] < a[pos] a[pos−1]<a[pos],那么 [ l , p o s ] [l, pos] [l,pos] 便可作为一个新的区间,便可缩小区间范围,至于这个 p o s pos pos 怎么取很明显可以二分。
注意特判 n = 1 n = 1 n=1 的情况
#include <bits/stdc++.h> const int N = 1e5 + 10; typedef long long ll; using namespace std; void solve() { } int main() { int n; cin>>n; int l=1,r=n; int arr[n+1]={0}; if(n==1) { cout<<"! "<<1<<endl; return 0; } cout << "? " << l << endl; cout.flush(); cin >> arr[l]; cout << "? " << r << endl; cout.flush(); cin >> arr[r]; while(l<r) { int mid=l+r>>1; if(arr[mid]==0) { cout<<"? "<<mid<<endl; cout.flush(); cin>>arr[mid]; } if(arr[mid+1]==0) { cout<<"? "<<mid+1<<endl; cout.flush(); cin>>arr[mid+1]; } if(arr[mid]<arr[mid+1]) r=mid; else { l=mid+1; } } cout<<"! "<<l<<endl; cout.flush(); }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。