Description
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;
}