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

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

  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. div.2/C. They Are Everywhere<two pointer>

    题意: 给出包含n (3<=n<=100000)个字符的字符串,计算出包含所有类型字符的最小区间长度. 题解: Two pointer.注意区间的处理. #include<cstdi ...

  2. HDU 2102 A计划 经典搜索

    A计划 Time Limit : 3000/1000ms (Java/Other)   Memory Limit : 32768/32768K (Java/Other) Total Submissio ...

  3. Extjs视频

    Extjs视频http://www.youku.com/playlist_show/id_19343298.html ExtJs视频教程(关东升) 智捷关东升老师ExtJs视频教程AJAX框架-Ext ...

  4. 基于VirtualBox 安装和配置Fuel OpenStack(V6.1)

    1.环境准备 准备一台内存较大的主机,12G以上 下载安装VirtualBox及其匹配的扩展包 virtualbox: http://download.virtualbox.org/virtualbo ...

  5. MongoDB如何设置权限(类似关系型数据库的用户名和密码)

    MongoDB 缺省是没有设置鉴权的,业界大部分使用 MongoDB 的项目也没有设置访问权限.这就意味着只要知道 MongoDB 服务器的端口,任何能访问到这台服务器的人都可以查询和操作 Mongo ...

  6. 设置自己Eclipse代码风格(内部)

    http://www.cnblogs.com/farseer810/p/4391318.html 经过这几次的代码提交,发现很多人的代码风格不够规范.个人认为很有必要强制性规定一下代码的规范. 整体来 ...

  7. java开发地三天——数据库介绍

    又是一天萌萌哒地过去了,今天是处理数据库的部分.SQL Server 2008,这东西是上学期搞MFC的时候接触到的,那时候话说安装就是一个大问题,然后在学SQL语句的时候感觉还好,一切都还过得去.现 ...

  8. java删除文件夹 Java中实现复制文件或文件夹

    删除文件夹 import java.io.File; public class DeleteDir { /** * @param args */ public static void main(Str ...

  9. JS——无缝滚动

    1.描述——无缝滚动图片 2.代码 <!DOCTYPE html> <html> <head> <meta charset="UTF-8" ...

  10. Spark+ECLIPSE+JAVA+MAVEN windows开发环境搭建及入门实例【附详细代码】

    http://blog.csdn.net/xiefu5hh/article/details/51707529 Spark+ECLIPSE+JAVA+MAVEN windows开发环境搭建及入门实例[附 ...