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. 20155303 2016-2017-2 《Java程序设计》第二周学习总结

    20155303 2016-2017-2 <Java程序设计>第二周学习总结 教材学习内容总结 『注意』 "//"为单行批注符: "/*"与&quo ...

  2. VS2005 与虚拟机的那点事

      好不容易把VS2008装上了,每次F5编译的时候,程序自动退出,意外的是VS2005也是同样的结果.好在有像我一样的好心人,愿意把解决的方法与大家共享.     经过搜索找到了答案,原来是VMwa ...

  3. 视频聊天插件:AnyChat使用攻略之iOS开发指南

    AnyChat使用攻略之iOS开发指南 这套攻略主要指导刚开始使用AnyChat SDK For iOS的同学,快速搭建SDK环境,和实现音视频开发流程. (需要工程案例文件可联系我们) 在iOS平台 ...

  4. 51Nod P1100 斜率最大

    传送门: https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1100 由于2 <= N <= 10000, 所以 ...

  5. java实现红包的分配算法

    个人推测,微信红包在发出的时候已经分配好金额.比如一个10元的红包发给甲乙丙三个人,其实在红包发出去的时候,已经确定了第一个会领取多少,第二个会领取多少金额. 而不是在领取的时候才计算的.下面贴出实现 ...

  6. python 关键字的操作

    声明:本文章默认使用的是python 3.6.1 1.要想当个牛逼的程序员,就要精通各种hello world的写法,当然,我不牛逼,只能用python去写^..^! print("Hell ...

  7. 谈谈ASP.NET Core中的ResponseCaching

    前言 前面的博客谈的大多数都是针对数据的缓存,今天我们来换换口味.来谈谈在ASP.NET Core中的ResponseCaching,与ResponseCaching关联密切的也就是常说的HTTP缓存 ...

  8. 算法题丨4Sum

    描述 Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + c + d = ...

  9. solr云的简单搭建(了解)

    1.认识系统架构 1.1.集群概述 1.1.1.单点服务器的问题 我们之所以要学习集群,是因为单点服务器,存在一系列的问题. 我们以前学习的JavaEE项目,都是部署在一台Tomcat上,所有的请求, ...

  10. Swagger: 一个restful接口文档在线生成+功能测试软件

    一.什么是 Swagger? Swagger 是一款RESTFUL接口的文档在线自动生成+功能测试功能软件.Swagger 是一个规范和完整的框架,用于生成.描述.调用和可视化 RESTful 风格的 ...