[JZOJ5609]【NOI2018模拟3.28】Tree

Description

给你一颗有 n 个点的树,其中 1 号点为根节点,每个点都有一个权值 val[i]
你可以从树中选择一些点,注意如果 i 与 j 都被选中且 j 在 i 的子树内,那么必须满足 val[i]>val[j]
请你求出最多能同时选出多少个点
n<=100000

Solution

有两种思路
第一种是先考虑一条链的情况,然后将它拓展到树
一条链的情况非常好做,一个最长上升子序列就好了
最长不下降子序列我们有一种附加数组的方法

那么现在可以用一个multiset来维护这个附加数组
每个儿子之间是不相干的,那么直接用启发式合并将它们合并到一起

考虑插入当前做到的子树的根节点
在multiset中找到第一个大于等于这个值的位置,并将它替换,若它已经是最后一个那就直接加入

最后的答案就是multiset的大小
O(Nlog2N)

第二种是先考虑N^2的DP,再用数据结构优化到N log N
设F[i][j]表示以i为根的子树,最大值为j最多能选多少个点(先离散化)
转移很显然,把j这一维改成前缀最大就是N^2的了

可以利用线段树合并、区间加或者修改完成上面的转移
复杂度 O(NlogN)

第一种代码1K左右,第二种2.5K+
据说第一种还要更快?

Code

第一种方法的代码

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <iostream>
#include <set>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fod(i,a,b) for(int i=a;i>=b;i--)
#define N 100005 
#define M 2005
using namespace std;
int l,n,fs[N],m,nt[2*N],dt[2*N],rt[N],n1,pr[N];
multiset<int> f[N];
multiset<int>::iterator it;
void hb(int k,int p)
{
    for(it=f[p].begin();it!=f[p].end();it++) f[k].insert(*it);
}
void dp(int k)
{
    int mx=0,mw=0;
    for(int i=fs[k];i;i=nt[i]) 
    {
        int p=dt[i];
        dp(p);
        if(f[rt[p]].size()>mx) mx=f[rt[p]].size(),mw=p;
    }
    if(!mw) rt[k]=++n1;
    else rt[k]=rt[mw];
    for(int i=fs[k];i;i=nt[i])
    {
        int p=dt[i];
        if(p!=mw) hb(rt[k],rt[p]);
    }
    it=f[rt[k]].lower_bound(pr[k]);
    int v=f[rt[k]].size();
    if(it!=f[rt[k]].end()) f[rt[k]].erase(it);
    v=f[rt[k]].size();
    f[rt[k]].insert(pr[k]);
}
void link(int x,int y)
{
    nt[++m]=fs[x];
    dt[fs[x]=m]=y;
}
int main()
{
    freopen("tree.in","r",stdin);
    freopen("tree.out","w",stdout); 
    cin>>n;
    fo(i,1,n) 
    {
        int x;
        scanf("%d%d",&pr[i],&x);
        if(x!=0) link(x,i);
    }
    dp(1);
    printf("%d\n",f[rt[1]].size());
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值