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

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

  bzoj2809: [Apio2012]dispatching

    把每个忍者先放到节点上,然后从下往上合并,假设到了这个点 总值 大于 预算,那么我们把这个 大根堆 的堆顶弹掉就好了,剩下的就是可合并堆。

    感谢prey :)

    

 #include <bits/stdc++.h>
#define rep(i, a, b) for (int i = a; i <= b; i++)
#define drep(i, a, b) for (int i = a; i >= b; i--)
#define REP(i, a, b) for (int i = a; i < b; i++)
#define mp make_pair
#define pb push_back
#define clr(x) memset(x, 0, sizeof(x))
#define xx first
#define yy second
using namespace std;
typedef pair<int, int> pii;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3fll;
//************************************************ const int maxn = ; struct Ed {
int u, v, nx; Ed() {}
Ed(int _u, int _v, int _nx) :
u(_u), v(_v), nx(_nx) {}
} E[maxn];
int G[maxn], edtot;
void addedge(int u, int v) {
E[++edtot] = Ed(u, v, G[u]);
G[u] = edtot;
} int pre[maxn], C[maxn], L[maxn], son[maxn];
struct node {
int key, dis, l, r, sz;
} heap[maxn];
int ndtot; int root[maxn];
ll M;
template <typename T> inline void MaxT (T &a, const T b) { if (a < b) a = b; }
ll ans = -;
int merge(int x, int y) {
if (!x) return y;
if (!y) return x;
if (heap[x].key < heap[y].key) swap(x, y);
heap[x].r = merge(heap[x].r, y);
heap[x].sz = heap[heap[x].l].sz + heap[heap[x].r].sz + ;
if (heap[heap[x].l].dis < heap[heap[x].r].dis) swap(heap[x].l, heap[x].r);
heap[x].dis = heap[heap[x].r].dis + ;
return x;
}
ll solve(int x) {
ll sum = C[x];
heap[root[x] = ++ndtot] = (node) {C[x], , , , };
for (int i = G[x], y; i; i = E[i].nx) {
sum += solve(y = E[i].v);
root[x] = merge(root[x], root[y]);
}
while (sum > M) sum -= heap[root[x]].key, root[x] = merge(heap[root[x]].l, heap[root[x]].r);
MaxT(ans, 1ll * heap[root[x]].sz * L[x]);
return sum;
} int main() {
int n; scanf("%d%lld", &n, &M);
int rt;
rep(i, , n) {
scanf("%d%d%d", pre + i, C + i, L + i);
son[pre[i]]++;
if (pre[i] == ) rt = i;
addedge(pre[i], i);
}
solve(rt);
printf("%lld\n", ans);
return ;
}

  bzoj4003: [JLOI2015]城池攻占

    堆上打个lazytag即可,可以表示成 tag_a * x + tag_b 的形式,标记的合并也很简单,tag_a2 * (tag_a1 * x + tag_b1) + tag_b2,乘开就好。

 #include <bits/stdc++.h>
#define rep(i, a, b) for (int i = a; i <= b; i++)
#define drep(i, a, b) for (int i = a; i >= b; i--)
#define REP(i, a, b) for (int i = a; i < b; i++)
#define mp make_pair
#define pb push_back
#define clr(x) memset(x, 0, sizeof(x))
#define xx first
#define yy second
using namespace std;
typedef pair<int, int> pii;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3fll;
//************************************************ const int maxn = ; struct Ed {
int u, v, nx; Ed() {}
Ed(int _u, int _v, int _nx) :
u(_u), v(_v), nx(_nx) {}
} E[maxn];
int G[maxn], edtot;
void addedge(int u, int v) {
E[++edtot] = Ed(u, v, G[u]);
G[u] = edtot;
} struct node {
int dis, l, r, sz;
ll key, tag_a, tag_b;
int id;
} heap[maxn];
int ndtot; ll hp[maxn], A[maxn], V[maxn];
int pre[maxn], root[maxn];
ll S[maxn], C[maxn]; void Push_down(int x) {
if (heap[x].tag_a == && heap[x].tag_b == ) return;
int l = heap[x].l, r = heap[x].r;
heap[l].tag_a *= heap[x].tag_a, heap[l].tag_b = heap[l].tag_b * heap[x].tag_a + heap[x].tag_b;
heap[r].tag_a *= heap[x].tag_a, heap[r].tag_b = heap[r].tag_b * heap[x].tag_a + heap[x].tag_b;
heap[l].key = heap[l].key * heap[x].tag_a + heap[x].tag_b;
heap[r].key = heap[r].key * heap[x].tag_a + heap[x].tag_b;
heap[x].tag_a = , heap[x].tag_b = ;
return;
} int merge(int x, int y) {
if (!x) return y;
if (!y) return x;
Push_down(x), Push_down(y);
if (heap[x].key > heap[y].key) swap(x, y);
heap[x].r = merge(heap[x].r, y);
heap[x].sz = heap[heap[x].l].sz + heap[heap[x].r].sz + ;
if (heap[heap[x].l].dis < heap[heap[x].r].dis) swap(heap[x].l, heap[x].r);
heap[x].dis = heap[heap[x].r].dis + ;
return x;
} int Stop[maxn], Peo[maxn];
int dep[maxn];
void solve(int x) {
for (int i = G[x], y; i; i = E[i].nx) {
dep[y = E[i].v] = dep[x] + ;
solve(y);
root[x] = merge(root[x], root[y]);
}
Push_down(root[x]);
while (root[x] && heap[root[x]].key < hp[x]) {
Push_down(root[x]);
Stop[heap[root[x]].id] = x;
Peo[x]++;
root[x] = merge(heap[root[x]].l, heap[root[x]].r);
}
if (root[x]) {
Push_down(root[x]);
if (A[x] == ) heap[root[x]].tag_b = V[x], heap[root[x]].key += V[x];
else heap[root[x]].tag_a = V[x], heap[root[x]].key *= V[x];
}
} int main() {
int n, m; scanf("%d%d", &n, &m);
rep(i, , n) scanf("%lld", hp + i);
rep(i, , n) {
scanf("%d%lld%lld", pre + i, A + i, V + i);
addedge(pre[i], i);
}
rep(i, , m) {
scanf("%lld%lld", S + i, C + i);
heap[++ndtot] = (node) {, , , , S[i], , , i};
root[C[i]] = merge(root[C[i]], ndtot);
}
solve();
rep(i, , n) printf("%d\n", Peo[i]);
rep(i, , m) printf("%d\n", Stop[i] ? dep[C[i]] - dep[Stop[i]] : dep[C[i]] + );
}

左偏树初步 bzoj2809 & bzoj4003的更多相关文章

  1. 【bzoj2809】[Apio2012]dispatching 左偏树

    2016-05-31  15:56:57 题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2809 直观的思想是当领导力确定时,尽量选择薪水少的- ...

  2. 【BZOJ4003】【JLOI2015】城池攻占(左偏树)

    题面 题目描述 小铭铭最近获得了一副新的桌游,游戏中需要用 m 个骑士攻占 n 个城池.这 n 个城池用 1 到 n 的整数表示.除 1 号城池外,城池 i 会受到另一座城池 fi 的管辖,其中 fi ...

  3. 【BZOJ2809】【APIO2012】Dispatching(左偏树)

    题面 Description 在一个忍者的帮派里,一些忍者们被选中派遣给顾客,然后依据自己的工作获取报偿.在这个帮派里,有一名忍者被称之为 Master.除了 Master以外,每名忍者都有且仅有一个 ...

  4. 左偏树(BZOJ4003)

    左偏树打个标记,没了. #include <cstdio> #include <vector> using namespace std; typedef long long l ...

  5. bzoj2809 [Apio2012]dispatching(左偏树)

    [Apio2012]dispatching Description 在一个忍者的帮派里,一些忍者们被选中派遣给顾客,然后依据自己的工作获取报偿.在这个帮派里,有一名忍者被称之为 Master.除了 M ...

  6. [BZOJ2809][Apio2012]dispatching(左偏树)

    首先对于一个节点以及它的子树,它的最优方案显然是子树下选最小的几个 用左偏树维护出每棵子树最优方案的节点,记录答案 然后它的这棵树可以向上转移给父节点,将所有子节点的左偏树合并再维护就是父节点的最优方 ...

  7. 【BZOJ2809】[APIO2012] dispatching(左偏树例题)

    点此看题面 大致题意: 有\(N\)名忍者,每名忍者有三个属性:上司\(B_i\),薪水\(C_i\)和领导力\(L_i\).你要选择一个忍者作为管理者,然后在所有被他管理的忍者中选择若干名忍者,使薪 ...

  8. 【bzoj2809】[Apio2012]dispatching (左偏树)

    我们需要枚举根,然后从其子树内选尽量多的点,薪水不超过M,可是暴力复杂度不对.于是考虑自下而上合并树(开始每棵树内只有一个节点,就是自己) 每个树是一个堆,我们维护树的节点个数和薪水总和,合并时,不断 ...

  9. bzoj2809 [Apio2012]dispatching——左偏树(可并堆)

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2809 思路有点暴力和贪心,就是 dfs 枚举每个点作为管理者: 当然它的子树中派遣出去的忍者 ...

随机推荐

  1. servlet中路径的获取

    1.获取项目的绝对路径 可以request.getRealPath("/"),但是这个方法已经废弃了,最好用this.getServletContext().getRealPath ...

  2. JSON文件存入MySQL数据库

    目标:将不同格式的JSON文件存入MySQL数据库 涉及的点有: 1. java处理JSON对象,直接见源码. 2. java.sql.SQLException: Incorrect string v ...

  3. instanceof实例和prototype

    var arr=[1,3,2];alert(arr instanceof Array); 返回true: 对于继承譬如一个Drag()拖拽的继承,我想加一个限制范围的拖拽 我需要写一个新的函数 fun ...

  4. lucene4.7 分页

    转载自http://my.oschina.net/MrMichael/blog/220782 我 们先来看下下面的问题,现在我们的索引里有2亿多的数据,那么现在的需求是,把索引里的全部数据,读取然后写 ...

  5. VBS脚本和HTML DOM自动操作网页

    VBS脚本和HTML DOM自动操作网页 2016-06-16 10:24 1068人阅读 评论(0) 收藏 举报  分类: Windows(42)  版权声明:本文为博主原创文章,未经博主允许不得转 ...

  6. HDU 3726 Graph and Queries 平衡树+前向星+并查集+离线操作+逆向思维 数据结构大综合题

    Graph and Queries Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Other ...

  7. 转:sqlplus与shell互相传值的几种情况

    sqlplus与shell互相传值的几种情况 情况一:在shell中最简单的调用sqlplus $cat test.sh #!/bin/sh sqlplus oracle/oracle@oracle& ...

  8. jQuery常用及基础知识总结(一)

    Attribute: $(”p”).addClass(css中定义的样式类型); 给某个元素添加样式$(”img”).attr({src:”test.jpg”,alt:”test Image”}); ...

  9. arm nop

    MOV R0,R0 这个语句相当于做一次无用功,也就相当于实现了NOP.       接下去就是怎么修改机器码的部分.先查询手册,查到MOV 的机器码是0xE1A0(此处可能不同,主要看自己IDA反汇 ...

  10. 简单 实现CombineFileInputFormat

    import java.io.DataOutput; import java.io.IOException;   import org.apache.hadoop.conf.Configuration ...