梦熊联盟 #7 Solution

前言

听闻梦熊联盟开了个新网站,遂来捧个人场。

感觉他们对入门难度有一些误解。

题目在

思路

可以将倍增的过程看作数组中两个相邻的数向某个数逼近的过程。

解题方法

由于 \(k\) 很小,考虑暴力逼近。

对于输入的 \(x\),若 \(a_1>x\)\(a_n<x\) 那么显然不会存在。

否则,找到第一个不小于 \(x\) 的数 \(a_y\),若 \(a_y=x\) 则显然存在。

否则,进行 \(k\) 次暴力逼近,若在某次逼近中左右区间的平均数为 \(x\),那么存在。

否则不存在。

复杂度

时间复杂度

每次查询时 \(O(\log n)\) 查找第一个不小于 \(x\) 的数,并进行 \(k\) 次暴力逼近,\(q\) 次询问,则时间复杂度为 \(O(n+q(k+\log n))=O(qk)\)

空间复杂度

仅需存储数组本身, 空间复杂度为 \(O(n)\)

Code

#include <iostream>
#include <algorithm>
using namespace std;
const int N = 1e3 + 10;
using ll = long long;
int n, q, k;
ll a[N], x, l, r, *ptr, mid;
void run()
{
    scanf("%d%lld", &k, &x);
    if (x > a[n] or x < a[1])
    {
        puts("No");
        return;
    }
    ptr = lower_bound(a + 1, a + n + 1, x);
    if (*ptr == x)
    {
        puts("Yes");
        return;
    }
    r = *ptr, l = *(ptr - 1);
    for (int i = 1; i <= k; i++)
    {
        mid = (l + r) >> 1ll;
        if (mid == x)
            return puts("Yes"), void();
        if (mid > x)
            r = mid;
        else
            l = mid;
    }
    puts("No");
}
int main()
{
    scanf("%d%d", &n, &q);
    for (int i = 1; i <= n; i++)
    {
        scanf("%lld", a + i);
    }
    for (int i = 1; i <= q; i++)
    {
        run();
    }
}
posted @ 2024-06-14 20:32  丝羽绫华  阅读(31)  评论(0编辑  收藏  举报