看着百度文库学习了一个。

  总的来说,左偏树这个可并堆满足 堆的性质 和 左偏 性质。

 

  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 }
View Code

相关文章:

  • 2021-07-19
  • 2021-11-23
  • 2021-05-22
  • 2022-03-08
  • 2021-11-10
猜你喜欢
  • 2021-09-12
  • 2022-02-05
  • 2022-01-11
  • 2021-08-30
  • 2021-09-01
  • 2022-12-23
  • 2022-02-18
相关资源
相似解决方案