Codeforces Round #700 (Div. 2) 虚拟参赛及补题

A题比较简单就不说了。
B题也比较简单,md,但是写法有问题。

  1. struct排序函数
bool cmp(node a,node b)
{
	return a.t<b.t;//点前不同,点后同。
}
  1. 而是要理清题意,我就排序关键字错了。

C题

  • 题目链接
  • 题意
    给你n个全排列;你每次问一个位置的数字,然后会返回一个 a i a_{i} ai ;要求你在100次内找到 k k k 使得 a k < m i n ( a k + 1 , a k − 1 ) a_{k}<min(a_{k+1},a_{k-1}) ak<min(ak+1,ak1)
  • 思路

首先判断 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[n1] 呈下降趋势,则 2 2 2 ~ n − 1 n-1 n1中必定存在拐点,即局部最小值。


这时候发现一个性质:
当一个区间 [ 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[pos1]<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();
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

疯狂的码泰君

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值