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

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

  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. 几个SQL语句笔试题

    1.表A和表B具有完全相同的结构,查出表A中有但表B中没有的数据: create table A( id int , name ), password ) ); create table B( id ...

  2. 快学Scala-第六章 对象

    知识点: 1.单例对象 使用object语法结构达到静态方法和静态字段的目的,如下例,对象定义某个类的单个实例,包含想要的特性,对象的构造器在该对象第一次被使用时调用. object Account{ ...

  3. 隐式intent启动电子邮件,不需要非电子邮件应用程序。

    Intent intent = new Intent(Intent.ACTION_SENDTO); intent.setType("text/plain"); intent.put ...

  4. AI 人工智能 探索 (十)

    呼叫事件图形结构如下 蓝色代表 警察局 红色代表警察 黄色代表 死亡人 蓝色球代表呼救人 黑色代表 敌人 警察目标是 攻击 黑色人,但 路中 会碰到 黄色人,如果警察有 救人功能 则会先救人去医院再看 ...

  5. 解决IOS safari在input focus弹出输入法时不支持position fixed的问题

    该文章为转载 我们在做移动web应用的时候,常常习惯于使用position:fixed把一个input框作为提问或者搜索框固定在页面底部.但在IOS的safari和webview中,对position ...

  6. mysql数据库主从备份

    近期实验室总是不给通知的就停电,导致我们在不停的恢复服务.在某一个断电的过程中,发现我们的项目管理工具redmine的硬盘挂掉了..因为是部署在虚拟机上的,也没做冗余,数据就丢了..于是反思,我们的m ...

  7. gnome配置

    1.gome-tweak-tool    gnome调校工具 2.gnome-shell插件(在gome-tweak-tool中) 可在https://extensions.gnome.org/中下载 ...

  8. windbg 之 如何定位进程入口点地址

    载入HelloWorld.exe之后我们看看加载了哪些模块:

  9. MyEclipse8.5优化经验

    第一步: 取消自动validation    validation有一堆,什么xml.jsp.jsf.js等等,我们没有必要全部都去自动校验一下,只是需要的时候才会手工校验一下!    取消方法:   ...

  10. centos dmesg

    linux dmesg命令详解   功能说明:显示开机信息. 语 法:dmesg [-cn][-s ] 补充说明:kernel会将开机信息存储在ring buffer,若是开机时来不及查看信息,可利用 ...