题面

给定一棵n个节点的有根树,编号依次为1到n,其中1号点为根节点。每个点有一个权值v_i。

你需要将这棵树转化成一个大根堆。确切地说,你需要选择尽可能多的节点,满足大根堆的性质:对于任意两个点i,j,如果i在树上是j的祖先,那么v_i>v_j。

请计算可选的最多的点数,注意这些点不必形成这棵树的一个连通子树。

分析

由于点不需要相邻,此题其实是树上的LIS,从叶子节点向根节点形成LIS

考虑LIS的\(O(nlogn)\)算法中用到的数组,用multiset对每个节点维护这样一个数组,存储子树内的值

向上的同时合并两个multiset,用启发式合并

时间复杂度应该是\(O(nlog^2n)\)

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<set>
#define maxn 200005
using namespace std;
int n;
struct edge{
int from;
int to;
int next;
}E[maxn<<1];
int head[maxn];
int sz;
void add_edge(int u,int v){
sz++;
E[sz].from=u;
E[sz].to=v;
E[sz].next=head[u];
head[u]=sz;
} int a[maxn];
multiset<int>s[maxn];
void merge(int x,int y){//启发式合并
if(s[x].size()<s[y].size()) swap(s[x],s[y]);
for(multiset<int>::iterator it=s[y].begin();it!=s[y].end();it++){
s[x].insert(*it);
}
}
void dfs(int x,int fa){
for(int i=head[x];i;i=E[i].next){
int y=E[i].to;
if(y!=fa){
dfs(y,x);
merge(x,y);
}
}
multiset<int>::iterator it=s[x].lower_bound(a[x]);
if(it==s[x].end()) s[x].insert(a[x]);
else{
s[x].erase(it);
s[x].insert(a[x]);
}
}
int main(){
int fa;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d %d",&a[i],&fa);
if(fa!=0){
add_edge(i,fa);
add_edge(fa,i);
}
}
dfs(1,0);
printf("%d\n",s[1].size());
}

BZOJ 4919 (树上LIS+启发式合并)的更多相关文章

  1. Special Segments of Permutation - CodeForces - 1156E (笛卡尔树上的启发式合并)

    题意 给定一个全排列\(a\). 定义子区间\([l,r]\),当且仅当\(a_l + a_r = Max[l,r]\). 求\(a\)序列中子区间的个数. 题解 笛卡尔树上的启发式合并. \(200 ...

  2. BZOJ 3123 主席树 启发式合并

    思路: 主席树 搞树上的k大 x+y-lca(x,y)-fa(lca(x,y)) 按照size小树往大树上插 启发式合并 n*log^2n的 搞定~ //By SiriusRen #include & ...

  3. BZOJ.3510.首都(LCT 启发式合并 树的重心)

    题目链接 BZOJ 洛谷 详见这. 求所有点到某个点距离和最短,即求树的重心.考虑如何动态维护. 两棵子树合并后的重心一定在两棵树的重心之间那条链上,所以在合并的时候用启发式合并,每合并一个点检查sz ...

  4. BZOJ 3123 [SDOI2013] 森林 - 启发式合并 主席树

    Description 给你一片森林, 支持两个操作: 查询$x$到$y$的$K$大值,  连接两棵树中的两个点 Solution 对每个节点$x$动态开权值线段树, 表示从$x$到根节点路径上权值出 ...

  5. 【csp模拟赛6】树上统计-启发式合并,线段树合并

    30%:暴力 40%:枚举L,R从L~n枚举,R每增大一个,更新需要的边(bfs实现)60%:枚举每条边, 计算每条边的贡献另外20%的数据:枚举每条边,计算每条边的贡献100%:对于每一条边统计 有 ...

  6. BZOJ 3545: [ONTAK2010]Peaks 启发式合并 + 离线 + Splay

    Description 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问,每组询问询 ...

  7. Codeforces 1009 F. Dominant Indices(长链剖分/树上启发式合并)

    F. Dominant Indices 题意: 给一颗无向树,根为1.对于每个节点,求其子树中,哪个距离下的节点数量最多.数量相同时,取较小的那个距离. 题目: 这类题一般的做法是树上的启发式合并,复 ...

  8. bzoj 4919 [Lydsy1706月赛]大根堆 set启发式合并+LIS

    4919: [Lydsy1706月赛]大根堆 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 599  Solved: 260[Submit][Stat ...

  9. BZOJ 4919: [Lydsy1706月赛]大根堆 set启发式合并

    这个和 bzoj 5469 几乎是同一道题,但是这里给出另一种做法. 你发现你要求的是一个树上 LIS,而序列上的 LIS 有一个特别神奇的 $O(n\log n) $ 做法. 就是维护一个单调递增的 ...

随机推荐

  1. FCC 成都社区·前端周刊 第 8 期

    01. 2018 前端开发者手册 这是一份 2018 前端开发手册,内容包括三个部分:前端工程实践.前端开发学习和前端开发工具. 详情:https://frontendmasters.com/book ...

  2. Django【第18篇】:Django之缓存

    Django 之缓存 一.缓存 由于Django是动态网站,所有每次请求均会去数据进行相应的操作,当程序访问量大时,耗时必然会更加明显,最简单解决方式是使用:缓存,缓存将一个某个views的返回值保存 ...

  3. CF547E Mike and Friends

    子串看起来就很SuffixStructures 于是上SAM 本来想着直接LCT 后来发现没法串定位(暴力匹配复杂度不对) 然后就离线吧,先建出来然后链加子树和,树剖就odk. 其实更直接的套路是线段 ...

  4. SpringBoot整合MyBatis-Plus代码自动生成类

    在springboot的test测试类下创建 MpGenerator.java   配置  MpGenerator.java public class MpGenerator { @Test publ ...

  5. SpringBoot整合redis把用户登录信息存入redis

    首先引入redis的jai包 <dependency> <groupId>org.springframework.boot</groupId> <artifa ...

  6. ELK整合Filebeat监控nginx日志

    ELK 日志分析 1. 为什么用到 ELK 一般我们需要进行日志分析场景:直接在日志文件中 grep. awk 就可以获得自己想要的信息.但在规模较大的场景中,此方法效率低下,面临问题包括日志量太大如 ...

  7. c++复习——类(1)

    1.  拷贝构造函数 //并没有搞懂 先存着吧  遇到实际情况再回来看看 拷贝构造函数在以下三种情况被调用: (1)当用一个已经初始化过的对象去初始化同类另一个对象时, 拷贝构造函数被调用. Samp ...

  8. 【CF1237C】Balanced Removals(降维)

    题意:三维平面上有n个点,每个点的坐标为(x[i],y[i],z[i]),n为偶数 现在要求取n/2次,每次取走一对点(x,y),要求没有未被取走的点在以x和y为对角点的矩形中 要求给出任意一组合法方 ...

  9. 前端HTTP缓存

    Web 缓存大致可以分为:数据库缓存.服务器端缓存(代理服务器缓存.CDN 缓存).浏览器缓存.其中前端比较关心的是浏览器缓存,包括今天要说的HTTP缓存和前面说过的cookie.localStora ...

  10. [CSP-S模拟测试]:购物(柯朵莉树)

    题目描述 $visit_world$有一个商店,商店里卖$N$个商品,第$i$个的价格为$a[i]$我们称一个正整数$K$是美妙的,当且仅当我们可以在商店里选购若干个商品,使得价格之和落在区间$[K, ...