看着百度文库学习了一个。
总的来说,左偏树这个可并堆满足 堆的性质 和 左偏 性质。
bzoj2809: [Apio2012]dispatching
把每个忍者先放到节点上,然后从下往上合并,假设到了这个点 总值 大于 预算,那么我们把这个 大根堆 的堆顶弹掉就好了,剩下的就是可合并堆。
感谢prey :)
1 #include <bits/stdc++.h> 2 #define rep(i, a, b) for (int i = a; i <= b; i++) 3 #define drep(i, a, b) for (int i = a; i >= b; i--) 4 #define REP(i, a, b) for (int i = a; i < b; i++) 5 #define mp make_pair 6 #define pb push_back 7 #define clr(x) memset(x, 0, sizeof(x)) 8 #define xx first 9 #define yy second 10 using namespace std; 11 typedef pair<int, int> pii; 12 typedef long long ll; 13 const int inf = 0x3f3f3f3f; 14 const ll INF = 0x3f3f3f3f3f3f3f3fll; 15 //************************************************ 16 17 const int maxn = 100005; 18 19 struct Ed { 20 int u, v, nx; Ed() {} 21 Ed(int _u, int _v, int _nx) : 22 u(_u), v(_v), nx(_nx) {} 23 } E[maxn]; 24 int G[maxn], edtot; 25 void addedge(int u, int v) { 26 E[++edtot] = Ed(u, v, G[u]); 27 G[u] = edtot; 28 } 29 30 int pre[maxn], C[maxn], L[maxn], son[maxn]; 31 struct node { 32 int key, dis, l, r, sz; 33 } heap[maxn]; 34 int ndtot; 35 36 int root[maxn]; 37 ll M; 38 template <typename T> inline void MaxT (T &a, const T b) { if (a < b) a = b; } 39 ll ans = -1; 40 int merge(int x, int y) { 41 if (!x) return y; 42 if (!y) return x; 43 if (heap[x].key < heap[y].key) swap(x, y); 44 heap[x].r = merge(heap[x].r, y); 45 heap[x].sz = heap[heap[x].l].sz + heap[heap[x].r].sz + 1; 46 if (heap[heap[x].l].dis < heap[heap[x].r].dis) swap(heap[x].l, heap[x].r); 47 heap[x].dis = heap[heap[x].r].dis + 1; 48 return x; 49 } 50 ll solve(int x) { 51 ll sum = C[x]; 52 heap[root[x] = ++ndtot] = (node) {C[x], 0, 0, 0, 1}; 53 for (int i = G[x], y; i; i = E[i].nx) { 54 sum += solve(y = E[i].v); 55 root[x] = merge(root[x], root[y]); 56 } 57 while (sum > M) sum -= heap[root[x]].key, root[x] = merge(heap[root[x]].l, heap[root[x]].r); 58 MaxT(ans, 1ll * heap[root[x]].sz * L[x]); 59 return sum; 60 } 61 62 int main() { 63 int n; scanf("%d%lld", &n, &M); 64 int rt; 65 rep(i, 1, n) { 66 scanf("%d%d%d", pre + i, C + i, L + i); 67 son[pre[i]]++; 68 if (pre[i] == 0) rt = i; 69 addedge(pre[i], i); 70 } 71 solve(rt); 72 printf("%lld\n", ans); 73 return 0; 74 }