左偏树初步 bzoj2809 & bzoj4003
看着百度文库学习了一个。
总的来说,左偏树这个可并堆满足 堆的性质 和 左偏 性质。
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 }
bzoj4003: [JLOI2015]城池攻占
堆上打个lazytag即可,可以表示成 tag_a * x + tag_b 的形式,标记的合并也很简单,tag_a2 * (tag_a1 * x + tag_b1) + tag_b2,乘开就好。
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 = 300005; 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 struct node { 31 int dis, l, r, sz; 32 ll key, tag_a, tag_b; 33 int id; 34 } heap[maxn]; 35 int ndtot; 36 37 ll hp[maxn], A[maxn], V[maxn]; 38 int pre[maxn], root[maxn]; 39 ll S[maxn], C[maxn]; 40 41 void Push_down(int x) { 42 if (heap[x].tag_a == 1 && heap[x].tag_b == 0) return; 43 int l = heap[x].l, r = heap[x].r; 44 heap[l].tag_a *= heap[x].tag_a, heap[l].tag_b = heap[l].tag_b * heap[x].tag_a + heap[x].tag_b; 45 heap[r].tag_a *= heap[x].tag_a, heap[r].tag_b = heap[r].tag_b * heap[x].tag_a + heap[x].tag_b; 46 heap[l].key = heap[l].key * heap[x].tag_a + heap[x].tag_b; 47 heap[r].key = heap[r].key * heap[x].tag_a + heap[x].tag_b; 48 heap[x].tag_a = 1, heap[x].tag_b = 0; 49 return; 50 } 51 52 int merge(int x, int y) { 53 if (!x) return y; 54 if (!y) return x; 55 Push_down(x), Push_down(y); 56 if (heap[x].key > heap[y].key) swap(x, y); 57 heap[x].r = merge(heap[x].r, y); 58 heap[x].sz = heap[heap[x].l].sz + heap[heap[x].r].sz + 1; 59 if (heap[heap[x].l].dis < heap[heap[x].r].dis) swap(heap[x].l, heap[x].r); 60 heap[x].dis = heap[heap[x].r].dis + 1; 61 return x; 62 } 63 64 int Stop[maxn], Peo[maxn]; 65 int dep[maxn]; 66 void solve(int x) { 67 for (int i = G[x], y; i; i = E[i].nx) { 68 dep[y = E[i].v] = dep[x] + 1; 69 solve(y); 70 root[x] = merge(root[x], root[y]); 71 } 72 Push_down(root[x]); 73 while (root[x] && heap[root[x]].key < hp[x]) { 74 Push_down(root[x]); 75 Stop[heap[root[x]].id] = x; 76 Peo[x]++; 77 root[x] = merge(heap[root[x]].l, heap[root[x]].r); 78 } 79 if (root[x]) { 80 Push_down(root[x]); 81 if (A[x] == 0) heap[root[x]].tag_b = V[x], heap[root[x]].key += V[x]; 82 else heap[root[x]].tag_a = V[x], heap[root[x]].key *= V[x]; 83 } 84 } 85 86 int main() { 87 int n, m; scanf("%d%d", &n, &m); 88 rep(i, 1, n) scanf("%lld", hp + i); 89 rep(i, 2, n) { 90 scanf("%d%lld%lld", pre + i, A + i, V + i); 91 addedge(pre[i], i); 92 } 93 rep(i, 1, m) { 94 scanf("%lld%lld", S + i, C + i); 95 heap[++ndtot] = (node) {0, 0, 0, 1, S[i], 1, 0, i}; 96 root[C[i]] = merge(root[C[i]], ndtot); 97 } 98 solve(1); 99 rep(i, 1, n) printf("%d\n", Peo[i]); 100 rep(i, 1, m) printf("%d\n", Stop[i] ? dep[C[i]] - dep[Stop[i]] : dep[C[i]] + 1); 101 }