题解:CF1997E Level Up
Aurora5090 · · 题解
CF 传送门
提供一个
容易想到根号分治,我们先离线询问,按询问的
根据套路,枚举
预处理出每个
这部分时间是
随后解决
在这部分,我们的等级最多只有
第一直觉的做法可能是会带个
可以找到等级
然后回答询问,如果这个端点在等级
这样的话是
其实稍微改一下就可以做到严格
依赖一个观察:随着我们
证明比较简单,考虑等级
实际上就是
在移动过程中,暴力维护
每次可以
挪指针的时候访存比较垃圾,好像
代码
#include <bits/stdc++.h>
using namespace std;
struct node
{
int pos, k, id;
inline bool operator<(const node &n) const
{
return k < n.k;
}
};
const int maxn = 2e5 + 5, B = 1000;
int n, q;
int a[maxn], ans[maxn];
node ask[maxn];
int col[maxn];
int ptr[205], val[205], bel[maxn];
void build(int qk)
{
int level = 1, cnt = 0;
for (int i = 1; i <= n; i++)
{
cnt += (a[i] >= level);
col[i] = (a[i] >= level);
if (cnt >= qk)
level++, cnt = 0;
}
}
void init()
{
int level = 1, cnt = 0;
for (int i = 1; i <= n; i++)
{
int v = a[i] >= level;
cnt += v;
val[level] += v;
col[i] = v;
bel[i] = level;
if (cnt >= B)
ptr[level] = i, level++, cnt = 0;
}
ptr[level] = n;
}
void solve(int qk)
{
for (int id = 1; id <= 200; id++)
{
if (ptr[id] == 0 || ptr[id] >= n)
break;
if (ptr[id] < ptr[id - 1])
ptr[id] = ptr[id - 1], val[id] = 0;
while (val[id] < qk && ptr[id] < n)
{
int i = ++ptr[id];
if (a[i] >= id)
{
val[id]++;
if (col[i] == 1)
val[bel[i]]--;
bel[i] = id;
col[i] = 1;
}
else
{
bel[i] = 0;
col[i] = 0;
}
}
}
}
int main()
{
ios::sync_with_stdio(false), cin.tie(0);
cin >> n >> q;
for (int i = 1; i <= n; i++)
cin >> a[i];
for (int i = 1; i <= q; i++)
{
cin >> ask[i].pos >> ask[i].k;
ask[i].id = i;
}
sort(ask + 1, ask + 1 + q);
int pre = 0;
int flag = true;
for (int i = 1; i <= q; i++)
{
auto [qpos, qk, qid] = ask[i];
if (qk <= B)
{
if (pre != qk)
build(qk);
}
else
{
if (flag == true)
init(), flag = false;
if (pre != qk)
solve(qk);
}
ans[qid] = col[qpos];
pre = qk;
}
for (int i = 1; i <= q; i++)
cout << (ans[i] == 0 ? "NO\n" : "YES\n");
// cout.flush();
// system("Pause");
return 0;
}