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

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

  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. Android中如何将Bitmap byte裸数据转换成Bitmap图片int数据

    Android中如何将Bitmap byte裸数据转换成Bitmap图片int数据 2014-06-11 10:45:14   阅读375次 我们在JNI中处理得到的BMP图片Raw数据,我们应该如何 ...

  2. IE6下整站的bug详解

    <1>文字不居中:加一个行高: <2>png文件作为背景不显示: <!--[if IE 6]> <script src="js/DD_belated ...

  3. Linux设置某软件开机自动启动的方法

    方法一 将启动命令写到系统启动时会自动调用的脚本中 echo "/usr/local/apache2/bin/apachectl start" >> /etc/rc.d ...

  4. springMVC拦截器简单配置

    <!-- 拦截器 -->    <mvc:interceptors>        <mvc:interceptor>            <!-- 拦截所 ...

  5. hdu_3564_Another LIS(线段树+LIS)

    题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=3564 题意:给你N个数的位置.数i的位置为第i个数,比如 0 0 2,表示1插在第0个位置,此时数列为 ...

  6. hibernate不能自动生成表的原因总结

    1. upate->create <property name="hbm2ddl.auto">create</property> 2. 2.Mappi ...

  7. 无法加载shockwave flash

    热心网友 360浏览器的话,浏览器——工具——选项(非Internet选项)——高级设置——FLASH, 默认使用PPAPI Flash(需要重启浏览器) 默认使用NPAPI Flash(需要重启浏览 ...

  8. 使用float和display:block将内联元素转换成块元素的不同点

    使用float和display:block将内联元素转换成块元素的不同点 使用float和display:block将内联元素转换成块元素的不同点:内联元素可以转换成块级元素,常用的方法比如可以为内联 ...

  9. ntopng汉化记录

    对应版本为 ntopng-1.2.0_r8116.tgz 1.

  10. POJ 2155 Matrix(二维树状数组)

    与以往不同的是,这个树状数组是二维的,仅此而已 #include <iostream> #include <cstdio> #include <cstring> # ...