「JLOI 2015」城池攻佔「左偏樹」
阿新 • • 發佈:2019-02-06
對每個點維護一個左偏樹(小根可並堆),一開始把騎士插入
然後dfs,從下往上把騎士送上去
每次在取左偏樹的堆頂找死亡騎士,不斷pop,直到堆頂騎士不會死亡為止
然後最後在根上打修改懶標記(加或乘)
#include <cstdio>
#include <vector>
using namespace std;
typedef long long LL;
const int N = 3e5 + 10;
int n, m, f[N], op[N], s[N], t[N];
LL h[N], atk[N], num[N];
int ans[N], dep[N];
struct Node {
int l, r, d, id;
LL val, add, mul;
void Add(LL x) { add += x; val += x; }
void Mul(LL x) { mul *= x; add *= x; val *= x;}
} node[N << 2];
const Node null = {0, 0, 0, 0, 0LL, 0LL, 1LL};
int node_cnt;
void pushd(int u) {
if(!u) return ;
Node & rt = node[u];
if(!rt.mul) return ;
Node & l = node[node[u].l], & r = node[node[u].r];
if(rt.mul != 1) {
l.mul *= rt.mul; l.add *= rt.mul; l.val *= rt.mul;
r.mul *= rt.mul; r.add *= rt.mul; r.val *= rt.mul;
rt.mul = 1;
}
if(rt.add) {
l.add += rt.add; l.val += rt.add;
r.add += rt.add; r.val += rt.add;
rt.add = 0;
}
}
struct LeTree { //Leftist Tree
int rt;
LeTree() { rt = 0; }
int merge(int a, int b) {
pushd(a); pushd(b);
if(!a || !b) return a | b;
if(node[a].val > node[b].val) swap(a, b);
Node & rt = node[a];
rt.r = merge(rt.r, b);
if(node[rt.l].d < node[rt.r].d) swap(rt.l, rt.r);
rt.d = node[rt.r].d + 1;
return a;
}
inline void insert(LL x, int id) {
Node & u = node[++ node_cnt];
u = null; u.id = id; u.val = x;
rt = merge(rt, node_cnt);
}
inline bool empty() { return !rt; }
inline LL top() { return node[rt].val; }
inline int topi() { return node[rt].id; }
inline void pop() {
if(empty()) return ;
pushd(rt), rt = merge(node[rt].l, node[rt].r);
}
} heap[N];
vector<int> ch[N];
void dfs(int u) {
dep[u] = dep[f[u]] + 1;
for(int i = 0; i < ch[u].size(); i ++) {
int v = ch[u][i]; dfs(v);
heap[u].rt = heap[u].merge(heap[u].rt, heap[v].rt);
}
while(!heap[u].empty() && heap[u].top() < h[u])
{ ++ ans[u]; t[heap[u].topi()] = u; heap[u].pop(); };
if(!heap[u].empty()) {
if(op[u]) node[heap[u].rt].Mul(num[u]);
else node[heap[u].rt].Add(num[u]);
}
}
int main() {
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i ++)
scanf("%lld", &h[i]);
for(int i = 2; i <= n; i ++) {
scanf("%d%d%lld", &f[i], &op[i], &num[i]);
ch[f[i]].push_back(i);
}
for(int i = 1; i <= m; i ++) {
scanf("%lld%d", &atk[i], &s[i]);
heap[s[i]].insert(atk[i], i);
}
dfs(1);
for(int i = 1; i <= n; i ++)
printf("%d\n", ans[i]);
for(int i = 1; i <= m; i ++)
printf("%d\n", dep[s[i]] - dep[t[i]]);
return 0;
}