CF1326E Bombs
题意
N
N
N个数的全排列
p
p
p,现在将
N
N
N个数依次加入集合
A
A
A,如果这个位置
i
i
i上有炸弹,那么在加入这个数
p
i
p_i
pi后删除集合
A
A
A中最大的数,当所有数加入集合后,集合中最大的数为当次花费
现在给出
N
N
N个数
q
i
q_i
qi,对于每一个
i
i
i,求第
q
1
,
q
2
,
.
.
.
,
q
i
−
1
q_1,q_2,...,q_{i-1}
q1,q2,...,qi−1个位置上是炸弹时,最后的花费
题解
首先一个一个放进炸弹,
a
n
s
ans
ans只会递减
考虑现在放入炸弹
q
i
q_i
qi时,
a
n
s
ans
ans是否合法
对于炸弹
q
i
q_i
qi来说,他只会对
[
1
,
q
i
]
[1,q_i]
[1,qi]间的数有影响
反之对于
a
n
s
ans
ans来说,只有右边
[
p
o
s
a
n
s
,
N
]
[pos_{ans}, N]
[posans,N]的炸弹有影响
但是炸弹会先作用于比
a
n
s
ans
ans大的数,所以只要右边大于等于
a
n
s
ans
ans的数个数大于右边的炸弹数就行
记
b
[
i
]
b[i]
b[i]为
[
i
,
N
]
[i, N]
[i,N]中
≥
p
[
i
]
\geq p[i]
≥p[i]的数个数减去
[
i
,
N
]
[i, N]
[i,N]炸弹数
因此当前答案不合法条件就是
max
i
=
1
N
b
[
i
]
≤
0
\displaystyle\max_{i=1}^N b[i] \leq 0
i=1maxNb[i]≤0
那么每次加入炸弹
q
q
q,会令
b
b
b数组
[
1
,
q
]
[1, q]
[1,q]部分
−
1
-1
−1
每次
a
n
s
ans
ans不合法时,
a
n
s
ans
ans作为一个大的数,会对
[
1
,
p
o
s
a
n
s
]
[1,pos_{ans}]
[1,posans]间的数有影响,即
b
b
b数组
[
1
,
p
o
s
a
n
s
]
[1,pos{ans}]
[1,posans]部分
+
1
+1
+1
区间加法最值,线段树维护即可
代码
#include <bits/stdc++.h>
#define lc u<<1
#define rc u<<1|1
#define mid (t[u].l+t[u].r)/2
using namespace std;
typedef long long ll;
const int MAX = 3e5 + 10;
int N;
int p[MAX], q[MAX], pos[MAX];
struct SegmentTree {
int l, r, mx, tag;
void upd(int k) {
mx += k;
tag += k;
}
} t[MAX << 2];
void push_up(int u) { t[u].mx = max(t[lc].mx, t[rc].mx); }
void build(int u, int l, int r) {
t[u] = SegmentTree { l, r, 0, 0 };
if (l == r) return;
build(lc, l, mid); build(rc, mid + 1, r);
}
void push_down(int u) {
if (t[u].tag) {
t[lc].upd(t[u].tag);
t[rc].upd(t[u].tag);
t[u].tag = 0;
}
}
void update(int u, int ql, int qr, int k) {
if (ql <= t[u].l && t[u].r <= qr) {
t[u].upd(k);
return;
}
push_down(u);
if (ql <= mid) update(lc, ql, qr, k);
if (qr > mid) update(rc, ql, qr, k);
push_up(u);
}
int main() {
scanf("%d", &N);
for (int i = 1; i <= N; i++) scanf("%d", &p[i]), pos[p[i]] = i;
for (int i = 1; i <= N; i++) scanf("%d", &q[i]);
build(1, 1, N);
int ans = N;
printf("%d ", ans);
update(1, 1, pos[ans], 1);
for (int i = 1; i < N; i++) {
update(1, 1, q[i], -1);
while (t[1].mx <= 0) update(1, 1, pos[--ans], 1);
printf("%d ", ans);
}
return 0;
}