【BZOJ4003】【LOJ2107】【JLOI2015】城池攻占(可并堆)

Description

https://loj.ac/problem/2107


Solution

由于不会乘上负数,所以到达同一座城池的骑士相对战斗力不会变化。
所以我们用堆来维护一座城池中骑士的战斗力排名,将牺牲的骑士弹出、不断向上合并即可。

long long坑死人啊。。。


Code

/**************************************
 * Au: Hany01
 * Prob: [BZOJ4003][JLOI2015] 城池攻占
 * Date: Jul 26th, 2018
 * Email: [email protected]
**************************************/

#include<bits/stdc++.h>

using namespace std;

typedef long long LL;
typedef pair<int, int> PII;
typedef vector<int> VI;
#define File(a) freopen(a".in", "r", stdin), freopen(a".out", "w", stdout)
#define rep(i, j) for (register int i = 0, i##_end_ = j; i < i##_end_; ++ i)
#define For(i, j ,k) for (register int i = (j), i##_end_ = (k); i <= i##_end_; ++ i)
#define Fordown(i, j, k) for (register int i = (j), i##_end_ = (k); i >= i##_end_; -- i)
#define Set(a, b) memset(a, b, sizeof(a))
#define Cpy(a, b) memcpy(a, b, sizeof(a))
#define SZ(a) ((int)(a.size()))
#define ALL(a) a.begin(), a.end()
#define pb(a) push_back(a)
#define mp(a, b) make_pair(a, b)
#define x first
#define y second
#define INF (1e18)
#define INF1 (2139062143)
#define y1 wozenmezhemecaia 
#ifdef hany01
#define debug(...) fprintf(stderr, __VA_ARGS__)
#else
#define debug(...)
#endif

template<typename T> inline bool chkmax(T &a, T b) { return a < b ? a = b, 1 : 0; }
template<typename T> inline bool chkmin(T &a, T b) { return b < a ? a = b, 1 : 0; }

template<typename T> inline T read() {
    register char c_; register T _, __;
    for (_ = 0, __ = 1, c_ = getchar(); !isdigit(c_); c_ = getchar()) if (c_ == '-')  __ = -1;
    for ( ; isdigit(c_); c_ = getchar()) _ = (_ << 1) + (_ << 3) + (c_ ^ 48);
    return _ * __;
}

const int maxn = 300005;

int beg[maxn], v[maxn], nex[maxn], e, rt[maxn], n, m, st[maxn], ed[maxn], dep[maxn], cnt[maxn], A[maxn];
LL hp[maxn], V[maxn];

inline void add(int uu, int vv) { v[++ e] = vv, nex[e] = beg[uu], beg[uu] = e; }

struct Heap
{
    LL val[maxn], mult[maxn], plus[maxn];
    int lc[maxn], rc[maxn];

    inline void Mult(int t, LL dt) { if (t) val[t] *= dt, plus[t] *= dt, mult[t] *= dt; }
    inline void Plus(int t, LL dt) { if (t) val[t] += dt, plus[t] += dt; }

    inline void pushdown(int t) {
        if (mult[t] != 1) Mult(lc[t], mult[t]), Mult(rc[t], mult[t]), mult[t] = 1;
        if (plus[t]) Plus(lc[t], plus[t]), Plus(rc[t], plus[t]), plus[t] = 0;
    }

    int merge(int u, int v) {
        if (!u || !v) return u ^ v;
        if (val[u] > val[v]) swap(u, v);
        pushdown(u), rc[u] = merge(rc[u], v), swap(lc[u], rc[u]);
        return u;
    }

    inline int pop(int u) {
        pushdown(u);
        register int t = merge(lc[u], rc[u]);
        lc[u] = rc[u] = 0;
        return t;
    }

}heap;

void DFS(int u)
{
    int& t = rt[u];
    for (register int i = beg[u]; i; i = nex[i])
        dep[v[i]] = dep[u] + 1, DFS(v[i]), t = heap.merge(t, rt[v[i]]);
    while (t && heap.val[t] < hp[u]) ++ cnt[u], ed[t] = u, t = heap.pop(t);
    if (A[u]) heap.Mult(t, V[u]); else heap.Plus(t, V[u]);
}

int main()
{
#ifdef hany01
    File("bzoj4003");
#endif

    n = read<int>(), m = read<int>(), add(0, 1), hp[0] = INF;
    For(i, 1, n) hp[i] = read<LL>();
    For(i, 2, n) add(read<int>(), i), A[i] = read<int>(), V[i] = read<LL>();
    For(i, 1, m) heap.val[i] = read<LL>(), st[i] = read<int>(), heap.mult[i] = 1, rt[st[i]] = heap.merge(rt[st[i]], i);

    DFS(0);
    For(i, 1, n) printf("%d\n", cnt[i]);
    For(i, 1, m) printf("%d\n", dep[st[i]] - dep[ed[i]]);

    return 0;
}

猜你喜欢

转载自blog.csdn.net/hhaannyyii/article/details/81219181