Educational CodeForces Round 168 E Solution

闲话

大家好,我非常不喜欢暴力数据结构,所以我用树状数组和二分搜索过了这道题。

思路

首先,显然 \(k\) 越小越容易升级,也就是说 \(k\) 越小,逃跑的怪兽就越多。那么对于每一个位置 \(i\),我们可以求出一个阈值 \(c_i\),保证只要 \(k\) 不小于 \(c_i\),那么这个怪兽就一定不会逃跑。

解法

二分搜索。

使得等级为 \(a_i\) 的怪兽 \(i\) 在参数 \(k\) 下逃跑的充要条件是在 \(i\) 之前 Monocarp 的等级超越了 \(a_i\),也就是说在 \(i\) 之前已经打了至少 \(a_ik\) 个怪兽。快速查询一个位置在不同的 \(k\) 下有多少个怪物被打可以使用树状数组。

时间复杂度 \(O(n\log^2(2\times 10^5)+q)\)

代码

#include <iostream>
#include <tuple>
using namespace std;
const int N = 2e5 + 10;
int a[N], n, q, tr[N], idx = 1, l, r, mid, req[N];
inline void update(int x, int v)
{
    while (x < N)
    {
        tr[x] += v;
        x += (x & -x);
    }
}
inline int query(int x)
{
    int res = 0;
    while (x)
        res += tr[x], x -= (x & -x);
    return res;
}
inline bool check(int x, int v) // xth monster will fl, x=v
{
    return 1ll * a[x] * v <= query(v);
}
int main()
{
    scanf("%d%d", &n, &q);
    for (int i = 1; i <= n; i++)
    {
        scanf("%d", a + i);
    }
    for (int i = 1; i <= n; i++)
    {
        l = 1, r = n;
        while (l < r)
        {
            mid = (l + r) >> 1;
            if (check(i, mid))
                l = mid + 1;
            else
                r = mid;
        }
        update(l, 1);
        req[i] = l;
    }
    for (int i = 1, x, k; i <= q; i++)
    {
        scanf("%d%d", &x, &k);
        puts(k < req[x] ? "NO" : "YES");
    }
}

讲个笑话,赛时我把查询排序了导致多用了几十毫秒,虽然还是快的一批。大概四百多毫秒。

posted @ 2024-07-31 12:43  丝羽绫华  阅读(34)  评论(0)    收藏  举报