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");
}
}
讲个笑话,赛时我把查询排序了导致多用了几十毫秒,虽然还是快的一批。大概四百多毫秒。

浙公网安备 33010602011771号