bzoj4919: [Lydsy1706月赛]大根堆
怎么说呢,启发式合并真的是一个很玄学的东西啊
假如是一条链,那么答案就是LIS
对于一棵树,需要考虑当前点取不取。
假如当前点比下面所有LIS都要大,那么对于当前必选
假如只比一个LIS的最大值小,可以把这个最大值换成当前点权。
实际上,可以先把这个点权拿去替换他的lowerbound,前面的最大值没有被更新就没有影响,当前面最大值被更新,对于当前取这个点必然是成立的。
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> #include<set> using namespace std; int c[210000]; struct node { int x,y,next; }a[210000];int len,last[210000]; void ins(int x,int y) { len++; a[len].x=x;a[len].y=y; a[len].next=last[x];last[x]=len; } multiset<int>s[210000]; multiset<int> :: iterator it; void dfs(int x) { for(int k=last[x];k;k=a[k].next) { int y=a[k].y; dfs(y); for(it=s[y].begin();it!=s[y].end();it++) s[x].insert(*it); s[y].clear(); } it=s[x].lower_bound(c[x]); if(it!=s[x].end())s[x].erase(it); s[x].insert(c[x]); } int main() { freopen("a.in","r",stdin); freopen("a.out","w",stdout); int n,F,rt; scanf("%d",&n); len=0;memset(last,0,sizeof(last)); for(int i=1;i<=n;i++) { scanf("%d%d",&c[i],&F); if(F!=0)ins(F,i); else rt=i; } dfs(rt); printf("%d\n",s[rt].size()); return 0; }
pain and happy in the cruel world.