bzoj 2809 可并堆维护子树信息

对于每个节点,要在其子树中选尽量多的节点,并且节点的权值和小于一个定值.

建立大根堆,每个节点从儿子节点合并,并弹出最大值直到和满足要求.

 1 /**************************************************************
 2     Problem: 2809
 3     User: idy002
 4     Language: C++
 5     Result: Accepted
 6     Time:1224 ms
 7     Memory:6664 kb
 8 ****************************************************************/
 9
10 #include <cstdio>
11 #include <algorithm>
12 #define max(a,b) ((a)>(b)?(a):(b))
13 #define N 100010
14 using namespace std;
15
16 typedef long long dnt;
17
18 #define szof(nd) ((nd)?(nd)->sz:0)
19 struct Node {
20     int v, sz;
21     dnt s;
22     Node *ls, *rs;
23     inline void update() {
24         s = v + (ls?ls->s:0) + (rs?rs->s:0);
25         sz = 1 + szof(ls) + szof(rs);
26         if( szof(ls)<szof(rs) ) swap(ls,rs);
27     }
28 }pool[N], *tail=pool, *root[N];
29
30 int n, m;
31 int head[N], dest[N], next[N], etot;
32 dnt lead[N], cost[N];
33 int qu[N], bg, ed, master;
34
35 void adde( int u, int v ) {
36     etot++;
37     dest[etot] = v;
38     next[etot] = head[u];
39     head[u] = etot;
40 }
41 Node *newnode( int v ) {
42     Node *nd = ++tail;
43     nd->s = nd->v = v;
44     nd->ls = nd->rs = 0;
45     nd->sz = 1;
46     return nd;
47 }
48 Node *smerge( Node *na, Node *nb ) {
49     if( !na && !nb ) return 0;
50     if( !na ) return nb;
51     if( !nb ) return na;
52     if( na->v > nb->v ) {
53         na->rs = smerge( na->rs, nb );
54         na->update();
55         return na;
56     } else {
57         nb->rs = smerge( nb->rs, na );
58         nb->update();
59         return nb;
60     }
61 }
62 int main() {
63     scanf( "%d%d", &n, &m );
64     for( int i=1,p; i<=n; i++ ) {
65         scanf( "%d%lld%lld", &p, cost+i, lead+i );
66         if( p ) adde( p, i );
67         else master = i;
68     }
69     qu[bg=ed=1] = master;
70     while( bg<=ed ) {
71         int u=qu[bg++];
72         for( int t=head[u]; t; t=next[t] ) {
73             int v=dest[t];
74             qu[++ed] = v;
75         }
76     }
77     dnt ans = 0;
78     for( int i=ed; i>=1; i-- ) {
79         int u=qu[i];
80         root[u] = newnode(cost[u]);
81         for( int t=head[u]; t; t=next[t] ) {
82             int v=dest[t];
83             root[u] = smerge( root[u], root[v] );
84         }
85         while( root[u]->s > m )
86             root[u] = smerge( root[u]->ls, root[u]->rs );
87         ans = max( ans, lead[u]*root[u]->sz );
88     }
89     printf( "%lld\n", ans );
90 }

时间: 2024-10-01 22:01:17

bzoj 2809 可并堆维护子树信息的相关文章

【bzoj4530】[Bjoi2014]大融合 LCT维护子树信息

题目描述 小强要在N个孤立的星球上建立起一套通信系统.这套通信系统就是连接N个点的一个树. 这个树的边是一条一条添加上去的.在某个时刻,一条边的负载就是它所在的当前能够联通的树上路过它的简单路径的数量. 例如,在上图中,现在一共有了5条边.其中,(3,8)这条边的负载是6,因为有六条简单路径2-3-8,2-3-8-7,3-8,3-8-7,4-3-8,4-3-8-7路过了(3,8). 现在,你的任务就是随着边的添加,动态的回答小强对于某些边的负载的询问. 输入 第一行包含两个整数N,Q,表示星球的

【BZOJ3510】首都 LCT维护子树信息+启发式合并

[BZOJ3510]首都 Description 在X星球上有N个国家,每个国家占据着X星球的一座城市.由于国家之间是敌对关系,所以不同国家的两个城市是不会有公路相连的. X星球上战乱频发,如果A国打败了B国,那么B国将永远从这个星球消失,而B国的国土也将归A国管辖.A国国王为了加强统治,会在A国和B国之间修建一条公路,即选择原A国的某个城市和B国某个城市,修建一条连接这两座城市的公路. 同样为了便于统治自己的国家,国家的首都会选在某个使得其他城市到它距离之和最小的城市,这里的距离是指需要经过公

Loj 2230. 「BJOI2014」大融合 (LCT 维护子树信息)

链接:https://loj.ac/problem/2230 思路: 设立siz数组保存虚点信息,sum表示总信息 维护子树信息link操作和access操作需要进行一些改动 可参考博客:https://www.cnblogs.com/GXZlegend/p/7061458.html 实现代码; #include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include&l

【LCT维护子树信息】uoj207 共价大爷游长沙

这道题思路方面就不多讲了,主要是通过这题学一下lct维护子树信息. lct某节点u的子树信息由其重链的一棵splay上信息和若干轻儿子子树信息合并而成. splay是有子树结构的,可以在rotate,access的时候由儿子update到父亲,而轻儿子的信息update不上来,需要另外记一下. 记sum[x]为我们要求的子树信息,xu[x]为x的轻儿子的子树信息. (即,xu[x]由轻儿子的sum更新,sum[x]由xu[x]和splay子树上的儿子的sum更新. 这样我们就可以完整地用lct维

bzoj3510 首都 LCT 维护子树信息+树的重心

题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=3510 题解 首先每一个连通块的首都根据定义,显然就是直径. 然后考虑直径的几个性质: 定义:删去这个点以后剩下的连通块最大的最小的点为重心. 一棵树最多只能有两个相邻的直径: 一棵树的重心到一棵树中所有点的距离和最小.(这个也是题目的条件转化为重心的原因) 两棵树的并的重心在两棵树各自的重心的连线上. 一棵树添加或者删除一个节点,树的重心最多只移动一条边的位置. 有了这些性质,我们可以发现,

[XSY 1556] 股神小D LCT维护子树信息

实现 1 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <cctype> 6 #include <algorithm> 7 #include <vector> 8 using namespace std; 9 #define F(i, a, b) for (register int i = (a); i <= (b); i++)

[BJOI2014]大融合 LCT维护子树信息

Code: #include <cstdio> #include <algorithm> #include <cstring> #include <string> using namespace std; void setIO(string a){freopen((a+".in").c_str(),"r",stdin);} #define maxn 100009 #define ll long long int n,q

poj 2010 Moo University - Financial Aid 大顶堆维护最小和

题意: 有c有牛,从中选(n-1)/2头,使他们的得分中位数最大且需要的资金援助和不超过f. 分析: 堆的运用大顶堆维护最小和. 代码: //poj 2010 //sep9 #include <iostream> #include <queue> #include <algorithm> using namespace std; const int maxN=100024; int dpl[maxN],dpr[maxN]; priority_queue<int&g

BZOJ 2809 APIO2012 dispatching Treap+启示式合并 / 可并堆

题目大意:给定一棵树,选定一棵子树中的一些点,薪水和不能超过m,求点的数量*子树根节点的领导能力的最大值 考虑对于每一个节点,我们维护一种数据结构,在当中贪心寻找薪金小的雇佣. 每一个节点暴力重建一定不行.我们考虑可并数据结构.每一个节点将子节点的信息直接合并就可以 能够用启示式合并的Treap.也能够用可并堆 今天特意去学了这玩应0.0 先写了左偏树 然后又写了下随机堆-- 后者速度上更快一些 只是建议从左偏树開始学起 总之平衡树常数各种大就是了0.0 Treap+启示式合并 #include