F - LIS on Tree(LIS&DFS)

F - LIS on Tree(LIS&DFS)

題目傳送門

題意:給定一棵樹,求所有結點到根結點的LISLIS長度。

思路:顯然根據LISLIS的貪心思想,我們可以對其在樹上進行操作,與普通的LISLIS不同的是,一開始我們可以將存

LISLIS的數組進行初始化爲infinf,這樣每次只需要進行二分操作就行了,省去了直接添加到數組末尾的那一步。由於

不同LISLIS的路徑是不同的,所以每次搜索完一個結點就要回溯,還原到之前的LISLIS數組。

這樣問題就解決了。

時間複雜度:O(nlogn)O(nlogn)

AC代碼:

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5;
struct edge{
	int to,nt;
}e[N<<1];
int ans[N],d[N],a[N],cnt=1,h[N],n;//ans[i]存放答案,d[i]表示LIS數組 
void add(int u,int v){
	e[cnt]={v,h[u]};
	h[u]=cnt++;
}
void dfs(int u,int fa){
	int p=lower_bound(d+1,d+n+1,a[u])-d;//基於LIS的貪心思想 
	int tmp=d[p];
	d[p]=a[u];
	ans[u]=max(ans[fa],p);//取最大值. 
	for(int i=h[u];i;i=e[i].nt)
	{
		 int v=e[i].to;
		 if(v==fa) continue;
		 dfs(v,u);
	}
	d[p]=tmp;//回溯,因爲不同子樹的LIS路徑不同. 
}
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	for(int i=1,u,v;i<n;i++)
	{
		scanf("%d%d",&u,&v);
		add(u,v),add(v,u);
	}
	memset(d,0x3f,sizeof d);
	dfs(1,0);
	for(int i=1;i<=n;i++)
		printf("%d\n",ans[i]);
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章