CF1326E. Bombs

长度为$n$的序列$p_1…p_n$,和长度为$n$的序列$q_1…q_n$ 。

  • 将$q_i$放入集合$A$
  • 若$i$有炸弹,则移走$A$中最大的

$q_i$表示在$q_i$这个位置放上炸弹。问第$i$次放上炸弹时最后集合中最大的元素是多少。$q_1…q_i-1$放上炸弹。

考虑一个炸弹放入后会影响$[1,p_i]$中的元素。如果当前最大的我对$[1,pos[ans]]$贡献$1$。因为需要$x>=pos[ans]$才能将$ans-1$。

当我搜索每一次答案的时候判断此时有位置$\leq 0$。如果有则证明当前$ans$所有保护他的以及,比他大的都被炸弹掉了。然后我就继续更新。此时更新$[1,pos[ans-1]]$。观察比他大的数的区间是否以及都被干掉。

代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <cmath>
#include <cstring>
#include <vector>
#include <map>
using namespace std;
typedef long long ll;
#define ls pos << 1
#define rs pos << 1 | 1
const int N = 3e5 + 10;
const int mod = 1e9 + 7;
struct node
{
int lazy, maxx;
} tree[N << 2];

void pushup(int pos)
{
tree[pos].maxx = max(tree[ls].maxx, tree[rs].maxx);
}
void pushdown(int pos)
{
if (tree[pos].lazy)
{
int w = tree[pos].lazy;
tree[ls].lazy += w;
tree[rs].lazy += w;
tree[ls].maxx += w;
tree[rs].maxx += w;
tree[pos].lazy = 0;
}
}
void update(int pos, int ql, int qr, int w, int l, int r)
{
if (ql <= l && r <= qr)
{
tree[pos].lazy += w;
tree[pos].maxx += w;
return;
}
pushdown(pos);
int mid = (l + r) >> 1;
if (ql <= mid)
update(ls, ql, qr, w, l, mid);
if (qr > mid)
update(rs, ql, qr, w, mid + 1, r);
pushup(pos);
}
int n, pos[N];

int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; i++)
{
int x;
scanf("%d", &x);
pos[x] = i;
}
int ans = n;
update(1, 1, pos[n], 1, 1, n);
for (int i = 1; i <= n; i++)
{
int x;
scanf("%d", &x);

while (tree[1].maxx <= 0)
ans--, update(1, 1, pos[ans], 1, 1, n);
printf("%d ", ans);
update(1, 1, x, -1, 1, n);
}
}