Codeforces 490F Treeland Tour 树上的最长上升子序列

题目链接:点击打开链接

题意:

给定n个点的树。

下面n个数表示点权。

下面n-1行给出树。

找一条链,然后找出这条链中的点权组成的最长上升子序列。

求:最长上升子序列的长度。

思路:

首先是维护一条链然后求答案,但是如果直接树形dp(记录每个点u,u往下递增和u往下递减的长度)会使序列是来回的,即递增和递减都在同一条链上。

枚举每个点作为子序列的开头,然后维护一条链进行LIS的nlogn做法。

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;
import java.util.TreeSet;

public class Main {
	int max(int x, int y) {
		return x > y ? x : y;
	}
	static int N = 6050;
	int[] a = new int[N], len = new int[N];
	int n;
	int ans;
	ArrayList<Integer>[] G = new ArrayList[N];
	int[] Stack = new int[N];
	int top;
	void find(int u, int fa) {
		int pos = -1, val = -1;
		if(a[u]>Stack[top-1]){
			pos = -2;//-2表示新加了一个元素
			Stack[top++] = a[u];
			ans = max(ans, top);
		}
		else
		{
			int l = 0, r = top-1, siz = 0;
			while(l <= r){
				int mid = (l+r)>>1;
				if(Stack[mid] < a[u])
					l = mid+1;
				else
				{
					r = mid-1;
					siz = mid;
				}
			}
			pos = siz; val = Stack[siz];
			Stack[pos] = a[u];
		}
		for(int i = 0; i < G[u].size(); i++){
			int v = G[u].get(i); if(v == fa)continue;
			find(v, u);
		}
		if(pos != -1){
			if(pos == -2)top--;
			else {
				Stack[pos] = val;
			}
		}
	}
	void solve(int u) {
		for(int i = 0; i < G[u].size(); i++){
			int v = G[u].get(i);
			top = 0;
			Stack[top++] = a[u];
			find(v, u);
		}
	}

	void input() {
		n = cin.nextInt();
		for (int i = 1; i <= n; i++) {
			G[i] = new ArrayList();
			a[i] = cin.nextInt();
		}
		for (int i = 1, u, v; i < n; i++) {
			u = cin.nextInt();
			v = cin.nextInt();
			G[u].add(v);
			G[v].add(u);
		}
	}

	public void work() {
		input();
		ans = 1;
		for (int i = 1; i <= n; i++)
			solve(i);
		out.println(ans);
	}

	Main() {
		cin = new Scanner(System.in);
		out = new PrintWriter(System.out);
	}

	public static void main(String[] args) {
		Main e = new Main();
		e.work();
		out.close();
	}

	public Scanner cin;
	public static PrintWriter out;
}
时间: 2024-10-12 15:41:04

Codeforces 490F Treeland Tour 树上的最长上升子序列的相关文章

Codeforces 490F Treeland Tour(dp)

题目链接:Codeforces 490F Treeland Tour 类似于nlogn的递增上升子序列算法. #include <cstdio> #include <cstring> #include <vector> #include <algorithm> using namespace std; const int maxn = 6005; const int inf = 0x3f3f3f3f; int N, R[maxn], D[maxn], ans

Codeforces 490F Treeland Tour(离散化 + 线段树合并)

题目链接 Treeland Tour 题目就是让你求树上LIS 先离散化,然后再线段树上操作.一些细节需要注意一下. #include <bits/stdc++.h> using namespace std; #define rep(i, a, b) for (int i(a); i <= (b); ++i) #define dec(i, a, b) for (int i(a); i >= (b); --i) typedef long long LL; const int N =

Codeforces Round #279 (Div. 2) F. Treeland Tour(lis+dfs)

题目链接: huangjing 题意:告诉一个无向无环图,然后求在联通的路上的lis. 思路:枚举起点求lis 复杂度是n^2logn,貌似这复杂度对时间有点玄,估计是数据有点弱... 首先枚举起点,然后求lis,主要是用dfs求的,要用到回溯的思想,我觉得是只要更新了,就要保存那个操作,然后一旦这一次的搜索完成,那么就要立即回复g数组的值,因为有很多不同的路线,所以一条路走完后,就要回复以前的状态哦,免得影响另外一条路..我觉得尽管他们都说是暴力,但是我觉得这个题还是蛮好的... 题目: F.

Codeforces Round #345 Div.1 D.Zip-line 动态最长上升子序列

题意概述: 给出一个长度为N的序列和M组询问,问假设把某个位置的值改成另一个给出的值之后,序列的最长上升子序列的长度. N,M<=400000. 分析: 考虑某个位置的值改动后这个位置和最长上升子序列(lis)的关系: 1.这个位置包含在lis中(这种情况答案可能+1,可计算经过这个点的lis来等效决策). 2.这个位置不包含在lis中,那么需要看是否任意的lis都经过这个位置.如果是的话此决策的结果在原来长度基础上-1,否则就等于原来的长度. 有了大体思路,接下来想想维护. 任务1:对于任意位

D. Babaei and Birthday Cake---cf629D(最长上升子序列和+线段树优化)

http://codeforces.com/problemset/problem/629/D 题目大意: 我第一反应就是求最长上升子序列和  但是数值太大了  不能直接dp求  可以用线段树优化一下 #include<stdio.h> #include<string.h> #include<stdio.h> #include<math.h> #include<iostream> #include<algorithm> using na

14-高效求最长公共子序列(二维数组存不下)

/*                                   See LCS again时间限制:1000 ms  |  内存限制:65535 KB难度:3 描述 There are A, B two sequences, the number of elements in the sequence is n.m; Each element in the sequence are different and less than 100000. Calculate the length

POJ 2533 - Longest Ordered Subsequence(最长上升子序列) 题解

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置. 题目链接:http://poj.org/problem?id=2533 Description A numeric sequence of ai is ordered if a1 < a2 < ... < aN. Let the subsequence of the given numeric sequence (a1, a2, ..., aN) be any sequence (ai1, ai2, ..., aiK)

最长公共子序列的代码实现

关于最长公共子序列(LCS)的相关知识,http://blog.csdn.net/liufeng_king/article/details/8500084 这篇文章讲的比较好,在此暂时不再详说. 以下是我代码实现两种方式:递归+递推: 1 #include <bits/stdc++.h> 2 using namespace std; 3 int A[100]; 4 int B[100]; 5 6 //int B[]={2,3,5,6,9,8,4}; 7 int d[100][100]={0};

HDU 3998 Sequence (最长递增子序列+最大流SAP,拆点法)经典

Sequence Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1666    Accepted Submission(s): 614 Problem Description There is a sequence X (i.e. x[1], x[2], ..., x[n]). We define increasing subsequ