左偏树初步 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
", ans);
73     return 0;
74 }
View Code

  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
", Peo[i]);
100     rep(i, 1, m) printf("%d
", Stop[i] ? dep[C[i]] - dep[Stop[i]] : dep[C[i]] + 1);
101 }
View Code
原文地址:https://www.cnblogs.com/y7070/p/5183777.html