BZOJ4919[Lydsy1706月赛]大根堆
Description
一棵树,点带权,求我们把这棵树转化成一个大根堆最多能有多少节点
即对于任意两个点i,j,如果i在树上是j的祖先,那么
Solution
状态: 表示 点为根的子树中最大权值为 的时候最大点数
在对点 的时候我们把每个点的儿子的权值线段树合并一下就可以维护信息了
最后是看当前点对于我们的 有什么影响
我们发现我们这个点能带来的更新答案是
然后我们看看这个题哪里要改,如果 已经比可更新值大就不用更新了
最关键的性质:对于一个点 它的 数组是单调不降的(因为权值递增诶……)
在 的时候我们二分一下可以改的值,(具体看代码,易懂)
然后在权值线段树上改改就行了
这里 标记永久化 :对于线段树上的每个点,如果这个点的值被更新了(就是)
我们不需要下传标记,直接在查询的时候加上父链信息和即可
Code
#include<bits/stdc++.h>
using namespace std;
namespace yspm{
inline int read()
{
int res=0,f=1; char k;
while(!isdigit(k=getchar())) if(k=='-') f=-1;
while(isdigit(k)) res=res*10+k-'0',k=getchar();
return res*f;
}
const int N=200010;
struct node{
int sum,ls,rs;
#define ls(p) t[p].ls
#define rs(p) t[p].rs
#define sum(p) t[p].sum
}t[N<<5];
int rt[N],tot;
inline void update(int &p,int l,int r,int st,int ed,int val)
{
if(!p) p=++tot;
if(l<=st&&ed<=r) return sum(p)+=val,void();
int mid=(st+ed)>>1;
if(l<=mid) update(ls(p),l,r,st,mid,val);
if(r>mid) update(rs(p),l,r,mid+1,ed,val);
return ;
}
inline int query(int p,int l,int r,int x)
{
if(!p||!x) return 0;
int mid=(l+r)>>1;
if(x<=mid) return query(ls(p),l,mid,x)+sum(p);
else return query(rs(p),mid+1,r,x)+sum(p);
}
inline int merge(int x,int y,int l,int r)
{
if(!x||!y) return x+y;
if(l==r) return sum(x)+=sum(y),x;
int mid=(l+r)>>1,p=++tot;
sum(p)=sum(x)+sum(y);
ls(p)=merge(ls(x),ls(y),l,mid);
rs(p)=merge(rs(x),rs(y),mid+1,r);
return p;
}
vector<int> g[N];
int n,p[N],b[N],m;
inline void dfs(int x)
{
int siz=g[x].size();
for(int i=0;i<siz;++i)
{
int t=g[x][i]; dfs(t);
rt[x]=merge(rt[x],rt[t],1,m);
}
int val=query(rt[x],1,m,p[x]-1)+1;
if(val<=query(rt[x],1,m,p[x])) return ;
int l=p[x],r=m;
while(l<r)
{
int mid=(l+r+1)>>1;
if(query(rt[x],1,m,mid)<val) l=mid;
else r=mid-1;
}
update(rt[x],p[x],l,1,m,1);
return ;
}
signed main()
{
n=read();
for(int i=1;i<=n;++i)
{
p[i]=read(); b[++m]=p[i];
int fa=read(); g[fa].push_back(i);
}
sort(b+1,b+m+1); m=unique(b+1,b+m+1)-b-1;
for(int i=1;i<=n;++i) p[i]=lower_bound(b+1,b+m+1,p[i])-b;
dfs(1);
printf("%d\n",query(rt[1],1,m,m));
return 0;
}
}
signed main(){return yspm::main();}
Review
请认准标记永久化
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律