1. 程式人生 > >「JLOI 2015」城池攻佔「左偏樹」

「JLOI 2015」城池攻佔「左偏樹」

對每個點維護一個左偏樹(小根可並堆),一開始把騎士插入

然後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; }