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六月月赛]大根堆的更多相关文章

  1. 【BZOJ4919】[Lydsy六月月赛]大根堆 线段树合并

    [BZOJ4919][Lydsy六月月赛]大根堆 Description 给定一棵n个节点的有根树,编号依次为1到n,其中1号点为根节点.每个点有一个权值v_i. 你需要将这棵树转化成一个大根堆.确切 ...

  2. 【BZOJ4919】[Lydsy六月月赛]大根堆

    题解: 我觉得数据结构写成结构体还是有必要的 因为不然一道题里出现了两个相同的数据结构由于名字很像很容易出错 另外初始化用segmenttree(){ } 首先裸的dp很好想 f[i][j]表示在i点 ...

  3. bzoj 4921: [Lydsy六月月赛]互质序列

    4921: [Lydsy六月月赛]互质序列 Time Limit: 1 Sec  Memory Limit: 256 MBSubmit: 188  Solved: 110[Submit][Status ...

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

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

  5. [Lydsy1706月赛]大根堆

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

  6. 【BZOJ4922】[Lydsy六月月赛]Karp-de-Chant Number 贪心+动态规划

    [BZOJ4922][Lydsy六月月赛]Karp-de-Chant Number Description 卡常数被称为计算机算法竞赛之中最神奇的一类数字,主要特点集中于令人捉摸不透,有时候会让水平很 ...

  7. [BZOJ4920][Lydsy六月月赛]薄饼切割

    [BZOJ4920][Lydsy六月月赛]薄饼切割 试题描述 有一天,tangjz 送给了 quailty 一张薄饼,tangjz 将它放在了水平桌面上,从上面看下去,薄饼形成了一个 \(H \tim ...

  8. bzoj4919 [Lydsy1706月赛]大根堆

    Description 给定一棵n个节点的有根树,编号依次为1到n,其中1号点为根节点.每个点有一个权值v_i. 你需要将这棵树转化成一个大根堆.确切地说,你需要选择尽可能多的节点,满足大根堆的性质: ...

  9. BZOJ4919:[Lydsy1706月赛]大根堆(set启发式合并)

    Description 给定一棵n个节点的有根树,编号依次为1到n,其中1号点为根节点.每个点有一个权值v_i. 你需要将这棵树转化成一个大根堆.确切地说,你需要选择尽可能多的节点,满足大根堆的性质: ...

随机推荐

  1. NetFPGA-1G-CML Demo --- openflow_switch

    环境 ubuntu 14.04 vivado 15.2 ise 14.6 更多基础配置:http://www.cnblogs.com/wpqwpq/p/6771568.html 运行步骤 step1: ...

  2. JFinal项目发送邮件——jfinal-mail-plugin

    JFianl框架: JFinal 是基于 Java 语言的极速 WEB + ORM 框架,其核心设计目标是开发迅速.代码量少.学习简单.功能强大.轻量级.易扩展.Restful.在拥有Java语言所有 ...

  3. python全栈开发-Day13 内置函数

    一.内置函数 注意:内置函数id()可以返回一个对象的身份,返回值为整数. 这个整数通常对应与该对象在内存中的位置,但这与python的具体实现有关,不应该作为对身份的定义,即不够精准,最精准的还是以 ...

  4. php中函数和方法的区别

    php的方法就是定义在类里面的方法,一般不建议在方法内部定义方法,但是这种也可以这种叫做内部方法,一般只能本方法调用. 如果定义在同一个类中的方法,在同类的其他方法中调用是$this->方法名就 ...

  5. appiun滑动的简单封装

    import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.test ...

  6. Python内置函数(49)——isinstance

    英文文档: isinstance(object, classinfo) Return true if the object argument is an instance of the classin ...

  7. Python内置函数(19)——oct

    英文文档: oct(x) Convert an integer number to an octal string. The result is a valid Python expression. ...

  8. emqtt 试用(三)mqtt 知识

    一.概念 MQTT 协议客户端库: https://github.com/mqtt/mqtt.github.io/wiki/libraries 例如,mosquitto_sub/pub 命令行发布订阅 ...

  9. EasyUI 数据网格行过滤

    前段时间发现一个GridView很有用的功能,可以筛选数据,实现起来很简单 一.添加一个引用,这个可以自己去网上下载 <script type="text/javascript&quo ...

  10. RTSP连接中断重连的问题

    最近在调查的一个问题. 起因是我司的一款数据链产品,15km数字图传,测试时发现视频画面经常会出现马赛克或卡顿. 图传设置了10Mbps速率,而视频码流是4Mbps,按道理不应该出现这种问题. 经过几 ...