原题链接: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扩栈也是值得学习的经验。