1. 程式人生 > >BZOJ 4919: [Lydsy1706月賽]大根堆 啟發式合並

BZOJ 4919: [Lydsy1706月賽]大根堆 啟發式合並

bound 排序 線段樹 gist digi char insert dfs ext

我不會告訴你這是線段樹合並的好題的。。。

好吧我們可以搞一個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

BZOJ 4919: [Lydsy1706月賽]大根堆 啟發式合並