这题有两种做法来着。。。
第一种就是一开始想到的比较不靠谱,不过貌似可以过掉:
看从$1$号节点开始到$p$号节点最大需要的体力,记录单调上升的体力,询问的时候二分跳着走就可以了
不过精度问题还有可能爆double什么的QAQ
于是写了一半果断弃疗。。。结果有人说他过了【摔
第二种是正解,对于每个点我们可以先把下面的骑士都先做完然后还活着的全部搞到这个点上来,然后再看有谁死在这个点上了
所以我们要维护能都删除/查询最小值,合并,允许打标记的数据结构
貌似是可并堆喵!【完结撒花~
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 /************************************************************** 2 Problem: 4003 3 User: rausen 4 Language: C++ 5 Result: Accepted 6 Time:6872 ms 7 Memory:56988 kb 8 ****************************************************************/ 9 10 #include <cstdio> 11 #include <cmath> 12 #include <algorithm> 13 14 using namespace std; 15 typedef double lf; 16 typedef long long ll; 17 18 const int N = 3e5 + 5; 19 20 struct edge { 21 int next, to; 22 edge(int _n = 0, int _t = 0) : next(_n), to(_t) {} 23 } e[N]; 24 25 struct heap { 26 heap *ls, *rs; 27 ll v, tag_t, tag_a; 28 int dep, st, w; 29 30 void* operator new(size_t, int x, int y, ll z) { 31 static heap mempool[N], *c = mempool; 32 c -> ls = c -> rs = NULL; 33 c -> dep = 1, c -> v = z, c -> w = x, c -> st = y; 34 c -> tag_t = 1, c -> tag_a = 0; 35 return c++; 36 } 37 38 inline void Times(ll x) { 39 v *= x, tag_t *= x, tag_a *= x; 40 } 41 inline void Add(ll x) { 42 v += x, tag_a += x; 43 } 44 inline void push() { 45 if (ls) ls -> Times(tag_t); 46 if (rs) rs -> Times(tag_t); 47 tag_t = 1; 48 if (ls) ls -> Add(tag_a); 49 if (rs) rs -> Add(tag_a); 50 tag_a = 0; 51 } 52 53 #define Dep(p) (p ? p -> dep : 0) 54 inline void update() { 55 dep = Dep(rs) + 1; 56 } 57 58 friend heap* merge(heap *x, heap *y) { 59 if (!x) return y; 60 if (!y) return x; 61 if (x -> v > y -> v) swap(x, y); 62 x -> push(); 63 x -> rs = merge(x -> rs, y); 64 if (Dep(x -> rs) > Dep(x -> ls)) swap(x -> ls, x -> rs); 65 x -> update(); 66 return x; 67 } 68 #undef Dep 69 70 inline heap* pop() { 71 this -> push(); 72 return merge(ls, rs); 73 } 74 } *h[N]; 75 76 struct tree_node { 77 int fa, a, dep; 78 ll h, v; 79 } tr[N]; 80 81 inline ll read() { 82 static ll x, sgn; 83 static char ch; 84 x = 0, sgn = 1, ch = getchar(); 85 while (ch < '0' || '9' < ch) { 86 if (ch == '-') sgn = -1; 87 ch = getchar(); 88 } 89 while ('0' <= ch && ch <= '9') { 90 x = x * 10 + ch - '0'; 91 ch = getchar(); 92 } 93 return sgn * x; 94 } 95 96 int n, m; 97 int first[N], tot; 98 int ans1[N], ans2[N]; 99 100 inline void add_edge(int x, int y) { 101 e[++tot] = edge(first[x], y); 102 first[x] = tot; 103 } 104 105 #define y e[x].to 106 void dfs(int p) { 107 int x; 108 tr[p].dep = tr[tr[p].fa].dep + 1; 109 for (x = first[p]; x; x = e[x].next) { 110 dfs(y); 111 h[p] = merge(h[p], h[y]); 112 } 113 while (h[p] && h[p] -> v < tr[p].h) { 114 ++ans1[p], ans2[h[p] -> w] = tr[h[p] -> st].dep - tr[p].dep; 115 h[p] = h[p] -> pop(); 116 } 117 if (h[p]) 118 if (tr[p].a) h[p] -> Times(tr[p].v); 119 else h[p] -> Add(tr[p].v); 120 } 121 #undef y 122 123 int main() { 124 int i, x, c; 125 ll s; 126 n = read(), m = read(); 127 for (i = 1; i <= n; ++i) tr[i].h = read(); 128 for (i = 2; i <= n; ++i) { 129 x = read(), add_edge(x, i); 130 tr[i].fa = x , tr[i].a = read(), tr[i].v = read(); 131 } 132 for (i = 1; i <= m; ++i) { 133 s = read(), c = read(); 134 h[c] = merge(h[c], new(i, c, s)heap); 135 } 136 dfs(1); 137 while (h[1]) { 138 ans2[h[1] -> w] = tr[h[1] -> st].dep; 139 h[1] = h[1] -> pop(); 140 } 141 for (i = 1; i <= n; ++i) printf("%d\n", ans1[i]); 142 for (i = 1; i <= m; ++i) printf("%d\n", ans2[i]); 143 return 0; 144 }
By Xs酱~ 转载请说明
博客地址:http://www.cnblogs.com/rausen