bzoj 4919: [Lydsy六月月赛]大根堆
Description
给定一棵n个节点的有根树,编号依次为1到n,其中1号点为根节点。每个点有一个权值v_i。
你需要将这棵树转化成一个大根堆。确切地说,你需要选择尽可能多的节点,满足大根堆的性质:对于任意两个点i,j,如果i在树上是j的祖先,那么v_i>v_j。
请计算可选的最多的点数,注意这些点不必形成这棵树的一个连通子树。
Solution
思路比较直接
设 \(f[i][j]\) 表示\(i\)为子树的节点中,堆中最大值小于\(j\)的情况下能选的最多点数
转移时就是用一个前缀最大值更新一个后缀
用线段树维护即可,向上推时顺便把线段树合并
区间max直接打一个永久化标记
还要打区间加法标记,下放即可
注意各种地方都要下放,QwQ
#include<bits/stdc++.h>
using namespace std;
const int N=200005;
int n,head[N],nxt[N<<1],to[N<<1],num=0,m,a[N],b[N],cnt=0,rt[N],ans=0;
inline void link(int x,int y){nxt[++num]=head[x];to[num]=y;head[x]=num;}
struct node{
int ls,rs,la,w;
}tr[N*24];
inline void pushdown(int x){
int ls=tr[x].ls,rs=tr[x].rs;
if(ls)tr[ls].la+=tr[x].la,tr[ls].w=max(tr[x].w,tr[x].la+tr[ls].w);
if(rs)tr[rs].la+=tr[x].la,tr[rs].w=max(tr[x].w,tr[x].la+tr[rs].w);
tr[x].la=0;
}
inline void add(int &x,int l,int r,int sa,int se,int t){
if(!x)x=++cnt;
if(sa<=l && r<=se){tr[x].w=max(tr[x].w,t);return ;}
pushdown(x);
int mid=(l+r)>>1;
if(se<=mid)add(tr[x].ls,l,mid,sa,se,t);
else if(sa>mid)add(tr[x].rs,mid+1,r,sa,se,t);
else add(tr[x].ls,l,mid,sa,mid,t),add(tr[x].rs,mid+1,r,mid+1,se,t);
}
inline int merge(int x,int y){
if(!x||!y)return x+y;
pushdown(x);pushdown(y);
if(!tr[x].ls)
tr[x].ls=tr[y].ls,tr[tr[x].ls].w+=tr[x].w,tr[tr[x].ls].la+=tr[x].w+tr[x].la;
else if(!tr[y].ls)tr[tr[x].ls].w+=tr[y].w,tr[tr[x].ls].la+=tr[y].w+tr[y].la;
else tr[x].ls=merge(tr[x].ls,tr[y].ls);
if(!tr[x].rs)
tr[x].rs=tr[y].rs,tr[tr[x].rs].w+=tr[x].w,tr[tr[x].rs].la+=tr[x].w+tr[x].la;
else if(!tr[y].rs)tr[tr[x].rs].w+=tr[y].w,tr[tr[x].rs].la+=tr[y].w+tr[y].la;
else tr[x].rs=merge(tr[x].rs,tr[y].rs);
tr[x].w+=tr[y].w;
return x;
}
inline int qry(int x,int l,int r,int sa){
if(!x || !sa)return 0;
if(l==r)return tr[x].w;
int mid=(l+r)>>1;
pushdown(x);
if(sa<=mid)return max(qry(tr[x].ls,l,mid,sa),tr[x].w);
return max(qry(tr[x].rs,mid+1,r,sa),tr[x].w);
}
inline void dfs(int x){
for(int i=head[x];i;i=nxt[i])dfs(to[i]),rt[x]=merge(rt[x],rt[to[i]]);
add(rt[x],1,m,a[x],m,qry(rt[x],1,m,a[x]-1)+1);
}
inline void DFS(int x){
if(!x)return ;
ans=max(tr[x].w,ans);
pushdown(x);
DFS(tr[x].ls);DFS(tr[x].rs);
}
int main(){
freopen("pp.in","r",stdin);
freopen("pp.out","w",stdout);
scanf("%d",&n);
for(int i=1,x;i<=n;i++){
scanf("%d%d",&a[i],&x);
if(x)link(x,i);b[i]=a[i];
}
sort(b+1,b+n+1);m=unique(b+1,b+n+1)-b-1;
for(int i=1;i<=n;i++)a[i]=lower_bound(b+1,b+m+1,a[i])-b;
dfs(1);DFS(rt[1]);
cout<<ans<<endl;
return 0;
}
bzoj 4919: [Lydsy六月月赛]大根堆的更多相关文章
- 【BZOJ4919】[Lydsy六月月赛]大根堆 线段树合并
[BZOJ4919][Lydsy六月月赛]大根堆 Description 给定一棵n个节点的有根树,编号依次为1到n,其中1号点为根节点.每个点有一个权值v_i. 你需要将这棵树转化成一个大根堆.确切 ...
- 【BZOJ4919】[Lydsy六月月赛]大根堆
题解: 我觉得数据结构写成结构体还是有必要的 因为不然一道题里出现了两个相同的数据结构由于名字很像很容易出错 另外初始化用segmenttree(){ } 首先裸的dp很好想 f[i][j]表示在i点 ...
- bzoj 4921: [Lydsy六月月赛]互质序列
4921: [Lydsy六月月赛]互质序列 Time Limit: 1 Sec Memory Limit: 256 MBSubmit: 188 Solved: 110[Submit][Status ...
- bzoj 4919 [Lydsy1706月赛]大根堆 set启发式合并+LIS
4919: [Lydsy1706月赛]大根堆 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 599 Solved: 260[Submit][Stat ...
- [Lydsy1706月赛]大根堆
4919: [Lydsy1706月赛]大根堆 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 358 Solved: 150[Submit][Stat ...
- 【BZOJ4922】[Lydsy六月月赛]Karp-de-Chant Number 贪心+动态规划
[BZOJ4922][Lydsy六月月赛]Karp-de-Chant Number Description 卡常数被称为计算机算法竞赛之中最神奇的一类数字,主要特点集中于令人捉摸不透,有时候会让水平很 ...
- [BZOJ4920][Lydsy六月月赛]薄饼切割
[BZOJ4920][Lydsy六月月赛]薄饼切割 试题描述 有一天,tangjz 送给了 quailty 一张薄饼,tangjz 将它放在了水平桌面上,从上面看下去,薄饼形成了一个 \(H \tim ...
- bzoj4919 [Lydsy1706月赛]大根堆
Description 给定一棵n个节点的有根树,编号依次为1到n,其中1号点为根节点.每个点有一个权值v_i. 你需要将这棵树转化成一个大根堆.确切地说,你需要选择尽可能多的节点,满足大根堆的性质: ...
- BZOJ4919:[Lydsy1706月赛]大根堆(set启发式合并)
Description 给定一棵n个节点的有根树,编号依次为1到n,其中1号点为根节点.每个点有一个权值v_i. 你需要将这棵树转化成一个大根堆.确切地说,你需要选择尽可能多的节点,满足大根堆的性质: ...
随机推荐
- alpha-咸鱼冲刺day5
一,合照 emmmmm.自然还是没有的. 二,项目燃尽图 三,项目进展 !!!QAQ可以做到跟数据库交互了!!!!先来撒花花!(然后继续甲板) 四,问题困难 日常啥都不会,百度真心玩一年. 还得自学n ...
- iOS开发-FFmpeg深入分析
FFmpeg是相当强大的多媒体编解码框架,在深入分析其源代码之前必须要有基本的多媒体基础知识,否则其源代码会非常晦涩难懂.本文将从介绍一些基本的多媒体只是,主要是为研读ffmpeg源代码做准备,比如一 ...
- RxSwift(一)
文/iOS_Deve(简书作者) 原文链接:http://www.jianshu.com/p/429b5160611f 著作权归作者所有,转载请联系作者获得授权,并标注"简书作者" ...
- SpaceVim - 让你的vim变得更加高效和强大
SpaceVim 中文手册 项 目 主 页: https://spacevim.org Github 地址 : https://github.com/SpaceVim/SpaceVim SpaceVi ...
- python之路--day11---迭代器和生成器
迭代: 迭代是一个重复的过程,每次重复即一次迭代,并且每次迭代的结果都是下一次迭代的初始值 为什么要有迭代器: 数据类型的取值,字符串,列表,元组依靠索引可以取值,但是字典,集合,文件这些数据类型无法 ...
- linux的脚本应用for循环答应变量
#!/bin/bash for var in A B C ; do echo "var is $var" done
- MySQL关系表查询两个表的数据
如下,有四张表:游戏类型表,游戏表,点卡和游戏关系表,点卡表 CREATE TABLE `gamesType`( `tId` INT AUTO_INCREMENT NOT NULL PRIMARY K ...
- OAuth2.0学习(2-1)Spring Security OAuth2.0 开发指南
开发指南:http://www.cnblogs.com/xingxueliao/p/5911292.html Spring OAuth2.0 提供者实现原理: Spring OAuth2.0提供者实际 ...
- Spring Security 入门(1-3-1)Spring Security - http元素 - 默认登录和登录定制
登录表单配置 - http 元素下的 form-login 元素是用来定义表单登录信息的.当我们什么属性都不指定的时候 Spring Security 会为我们生成一个默认的登录页面. 如果不想使用默 ...
- java中数组、list、泛型集合的长度
1 java中的length属性是针对数组说的,比如说你声明了一个数组,想知道这个数组的长度则用到了length这个属性. 2 java中的length()方法是针对字符串String说的,如果想看这 ...