dfs序列思想+LIS Java扩栈

原题链接:https://ac.nowcoder.com/acm/contest/368/B
在这里插入图片描述
题解:直接从树的角度解决很难,因为不属于一种常用的树形数据结构,考虑dfs的序列的思想,可以将此问题转化为,求出根右左的dfs序列,然后对这个序列求最长上身子序列(LIS)即可解决,复杂度O(nlogn)。
需要注意的这个题,用Java写会再dfs的时候,会出现JVM栈溢出,所以只能通过90%,需要扩栈,C++不会出现这个问题。

import java.util.*;

public class Main implements Runnable{

    private final int mod = 1000000007, max = 100005;
    private int [] w = new int[max], dfsSqu = new int[max], l = new int[max], r = new int[max], dp = new int[max];
    private int cnt = 0;

    public static void main(String[] args) {
        new Thread(null, new Main(),"Thread-1", 1024*1024*10).start();
    }

    @Override
    public void run() {
        try{
            solve();
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    private void solve(){
        Scanner cin = new Scanner(System.in);
        int n = cin.nextInt();
        for(int i=1; i<=n; i++){
            w[i] = cin.nextInt();
        }
        for(int i=1; i<=n; i++){
            l[i] = cin.nextInt();
            r[i] = cin.nextInt();
        }

        dfs(1);//获取dfs序列

        //LIS
        dp[0] = dfsSqu[0];
        int len = 1;
        for(int i=1; i<cnt; i++){
            if(dfsSqu[i] > dp[len-1]){
                dp[len++] = dfsSqu[i];
            }else{
                dp[lower_bound(0, len-1, dfsSqu[i])] = dfsSqu[i];
            }
        }
        System.out.println(len);
    }

    private void dfs(int root){
        if(root == 0){
            return;
        }
        dfsSqu[cnt++] = w[root];
        dfs(r[root]);
        dfs(l[root]);
    }

    private int lower_bound(int lower, int higher, int key) {
        while(lower < higher){
            int mid = ((higher - lower) >> 1) + lower;
            if(key <= dp[mid]){
                higher = mid;
            }else{
                lower = mid+1;
            }
        }
        return lower;
    }
}




dfs序列的思想很值得学习,LIS也是经典dp之一,另外Java扩栈也是值得学习的经验。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值