BZOJ 4919: [Lydsy1706月赛]大根堆 启发式合并
我不会告诉你这是线段树合并的好题的。。。
好吧我们可以搞一个multiset在dfs时求出LIS(自带二分+排序)进行启发式合并,轻松加愉悦。。。
#include<cstdio> #include<iostream> #include<set> const int N=200010; #define R register int using namespace std; inline int g() { R ret=0; register char ch; while(!isdigit(ch=getchar())); do ret=ret*10+(ch^48); while(isdigit(ch=getchar())); return ret; } int n,m,cnt; multiset<int>s[N]; int vr[N<<1],nxt[N<<1],fir[N],w[N]; inline void add(int u,int v) {vr[++cnt]=v,nxt[cnt]=fir[u],fir[u]=cnt;} inline void dfs(int u) { for(R i=fir[u];i;i=nxt[i]) { R v=vr[i]; dfs(v); if(s[u].size()<s[v].size()) swap(s[u],s[v]); for(multiset<int>::iterator it=s[v].begin();it!=s[v].end();++it) s[u].insert(*it); } multiset<int>::iterator it=s[u].lower_bound(w[u]); if(it!=s[u].end()) s[u].erase(it); s[u].insert(w[u]); } signed main() { n=g(); for(R i=1,fa;i<=n;++i) { w[i]=g(),fa=g(); if(i==1) continue; add(fa,i); } dfs(1); printf("%d\n",s[1].size()); }
2019.04.20