【BZOJ4919】[Lydsy六月月赛]大根堆
题解:
我觉得数据结构写成结构体还是有必要的
因为不然一道题里出现了两个相同的数据结构由于名字很像很容易出错
另外初始化用segmenttree(){ }
首先裸的dp很好想
f[i][j]表示在i点,最大值<=j的点数最大值
看了别人的题解知道了可以用线段树合并来优化这个东西。。
我们考虑对于每个点,首先我们要合并它的子树
其实就是对于相同位置的点相加即可
然后考虑当前节点,我们应用f[v[x]-1]+1去更新v[x]-n之间的值(也就是取max操作)
不然是没法down的
1.当x,y其中有一个左二子没有的时候
就需要给它加一个sum标记
原因是,由于他没有左二子了,说明它对应的左二子的lazy值都是这个
所以要变成sum标记,对每一个子节点都加上这个
2.down的时候也要用lazy[fa]更新lazy[x] 原因是有sum[x]的存在
#include <bits/stdc++.h> using namespace std; const int N=1e6; const int INF=1e9; #define IL inline #define rint register int int n,m,fa[N],vv[N],head[N],l; struct re{ int a,b; }a[N],v[N]; IL int max(int x,int y) { int z; x>y?z=x:z=y; return(z); } IL int min(int x,int y) { int z; x<y?z=x:z=y; return(z); } void arr(int x,int y) { a[++l].a=head[x]; a[l].b=y; head[x]=l; } struct segmenttree { int cnt,rt[N],sum[N*20],ls[N*20],rs[N*20],lz[N*20]; #define mid ((h+t)>>1) segmenttree(){cnt=0;} IL void down(int x) { if (ls[x]) lz[ls[x]]=max(sum[x]+lz[ls[x]],lz[x]),sum[ls[x]]+=sum[x]; if (rs[x]) lz[rs[x]]=max(sum[x]+lz[rs[x]],lz[x]),sum[rs[x]]+=sum[x]; sum[x]=0; } int merge(int x,int y) { if (!x||!y) return x^y; down(x); down(y); if (!ls[x]) ls[x]=ls[y],lz[ls[x]]+=lz[x],sum[ls[x]]+=lz[x]; else if (!ls[y]) lz[ls[x]]+=lz[y],sum[ls[x]]+=lz[y]; else ls[x]=merge(ls[x],ls[y]); if (!rs[x]) rs[x]=rs[y],lz[rs[x]]+=lz[x],sum[rs[x]]+=lz[x]; else if (!rs[y]) lz[rs[x]]+=lz[y],sum[rs[x]]+=lz[y]; else rs[x]=merge(rs[x],rs[y]); lz[x]+=lz[y]; return x; } int query(int x,int h,int t,int pos) { if (x==0) return 0; if (h==t) return lz[x]; down(x); if (pos<=mid) return max(lz[x],query(ls[x],h,mid,pos)); else return max(lz[x],query(rs[x],mid+1,t,pos)); } void change(int &x,int h,int t,int h1,int t1,int k) { if (!x) x=++cnt; if (h1<=h&&t<=t1) { lz[x]=max(lz[x],k); return; } down(x); if (h1<=mid) change(ls[x],h,mid,h1,t1,k); if (mid<t1) change(rs[x],mid+1,t,h1,t1,k); } }se1; void dfs(int x,int fa) { int u=head[x]; while (u) { int v=a[u].b; dfs(v,x); se1.rt[x]=se1.merge(se1.rt[x],se1.rt[v]); u=a[u].a; } se1.change(se1.rt[x],1,n,vv[x],n,se1.query(se1.rt[x],1,n,vv[x]-1)+1); } bool cmp(re x,re y) { return(x.a<y.a); } int main() { // freopen("1.in","r",stdin); //freopen("1.out","w",stdout); cin>>n; for (int i=1;i<=n;i++) { cin>>v[i].a>>fa[i]; v[i].b=i; if (fa[i]) arr(fa[i],i); } sort(v+1,v+n+1,cmp); v[0].a=INF; int cnt=0; for (int i=1;i<=n;i++) { if (v[i].a!=v[i-1].a) cnt++; vv[v[i].b]=cnt; } dfs(1,0); int ans2=0; for(int i=1;i<=n;i++) ans2=max(ans2,se1.query(se1.rt[1],1,n,i)); cout<<ans2; return 0; }