题解:CF1997E Level Up
题目翻译
打怪操作是指,顺次对于
你每与
现在有若干组查询,每次查询
题目思路
首先考虑一个
由于每打
对于每一组
因为最多升级
那么我们可以使用主席树等数据结构求解。详见 牛客小白月赛 9 E. 换个角度思考 或 HDU 4417 Super Mario。
这样就得到了一个没有什么思维含量的
调和级数一共
由于随着
然而如果我们
这个预处理是
如果
把两个做法结合一下,取
-
k\leq B 暴力
\mathcal O(n\sqrt n) 。 -
k\gt B 预处理
\mathcal O(n\sqrt n) 。做查询
\mathcal O(n\log^2 n) 。
这样我们就在
因此,简单说一下过程,就是预处理
完整代码
CF submission 273823527
#include <bits/stdc++.h>
using namespace std;
#define getchar() p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1000000, stdin), p1 == p2) ? EOF : *p1++
char buf[1000000], *p1 = buf, *p2 = buf;
template <typename T>
void read(T &x)
{
x = 0;
int f = 1;
char c = getchar();
for (; c < '0' || c > '9'; c = getchar())
if (c == '-')
f = -f;
for (; c >= '0' && c <= '9'; c = getchar())
x = x * 10 + c - '0';
x *= f;
}
template <typename T, typename... Args>
void read(T &x, Args &...y)
{
read(x);
read(y...);
}
const int B = 448;
int n, Q;
int a[200020];
vector<array<int, 2>> q[200020];
bool ans[200020];
int sum[450][200020];
bool skip[200020];
int level[200020];
int main()
{
read(n, Q);
for (int i = 1; i <= n; i++)
{
read(a[i]);
if (a[i] <= B)
sum[a[i]][i]++;
}
for (int j = 1; j <= B; j++)
{
for (int i = 1; i <= n; i++)
sum[j][i] += sum[j - 1][i] + sum[j][i - 1] - sum[j - 1][i - 1];
}
for (int i = 1; i <= Q; i++)
{
int p, k;
read(p, k);
q[k].push_back({p, i});
}
for (int k = 1; k <= n; k++)
{
if (q[k].empty())
continue;
if (k <= B)
{
int lvl = 1;
int cnt = 0;
for (int i = 1; i <= n; i++)
{
skip[i] = 0;
if (a[i] < lvl)
{
skip[i] = 1;
continue;
}
cnt++;
if (cnt == k)
cnt = 0, lvl++;
}
for (auto [p, i] : q[k])
{
if (!skip[p])
ans[i] = 1;
}
}
else
{
sort(q[k].begin(), q[k].end());
int l = 1, r = 0, lvl = 1;
int j = 0;
auto check = [&](int r)
{ return (r - l + 1) - (sum[lvl - 1][r] - sum[lvl - 1][l - 1]) >= k; };
while (l <= n)
{
int L = l, R = n, r = n;
while (L <= R)
{
int mid = L + R >> 1;
if (check(mid))
R = (r = mid) - 1;
else
L = mid + 1;
}
while (j < q[k].size() && l <= q[k][j][0] && q[k][j][0] <= r)
level[q[k][j][0]] = lvl, j++;
l = r + 1;
lvl++;
}
for (auto [p, i] : q[k])
{
if (level[p] <= a[p])
ans[i] = 1;
}
}
}
for (int i = 1; i <= Q; i++)
puts(ans[i] ? "YES" : "NO");
return 0;
}