CF1326E Bombs 思维+线段树

CF1326E Bombs

题意

N N 个数的全排列 p p ,现在将 N N 个数依次加入集合 A A ,如果这个位置 i i 上有炸弹,那么在加入这个数 p i p_i 后删除集合 A A 中最大的数,当所有数加入集合后,集合中最大的数为当次花费
现在给出 N N 个数 q i q_i ,对于每一个 i i ,求第 q 1 , q 2 , . . . , q i 1 q_1,q_2,...,q_{i-1} 个位置上是炸弹时,最后的花费

题解

首先一个一个放进炸弹, a n s ans 只会递减
考虑现在放入炸弹 q i q_i 时, a n s ans 是否合法

对于炸弹 q i q_i 来说,他只会对 [ 1 , q i ] [1,q_i] 间的数有影响
反之对于 a n s ans 来说,只有右边 [ p o s a n s , N ] [pos_{ans}, N] 的炸弹有影响
但是炸弹会先作用于比 a n s ans 大的数,所以只要右边大于等于 a n s ans 的数个数大于右边的炸弹数就行

b [ i ] b[i] [ i , N ] [i, N] p [ i ] \geq p[i] 的数个数减去 [ i , N ] [i, N] 炸弹数
因此当前答案不合法条件就是 max i = 1 N b [ i ] 0 \displaystyle\max_{i=1}^N b[i] \leq 0

那么每次加入炸弹 q q ,会令 b b 数组 [ 1 , q ] [1, q] 部分 1 -1
每次 a n s ans 不合法时, a n s ans 作为一个大的数,会对 [ 1 , p o s a n s ] [1,pos_{ans}] 间的数有影响,即 b b 数组 [ 1 , p o s a n s ] [1,pos{ans}] 部分 + 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;
}

猜你喜欢

转载自blog.csdn.net/weixin_44282912/article/details/105036925