LIS on Tree

題目鏈接:LIS on Tree


最開始以爲要以某個點結尾,然後一直wa,其實是跟到這個點路徑上的任意最大LIS。

顯然我們就和普通求LIS一樣,維護一個權值數據結構,然後區間查詢維護。

因爲是路徑上,所以 res[x] =max ( res[fa] , val )

現在是一棵樹,每次回溯的時候取消操作即可。


AC代碼:

#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int N=2e5+10;
int n,a[N],res[N],mx[N<<2],m;
vector<int> g[N],v;
inline void add(int a,int b){g[a].push_back(b),g[b].push_back(a);}
#define mid (l+r>>1)
void change(int p,int l,int r,int x,int v){
	if(l==r){mx[p]=v;	return ;}
	if(x<=mid)	change(p<<1,l,mid,x,v);
	else change(p<<1|1,mid+1,r,x,v);
	mx[p]=max(mx[p<<1],mx[p<<1|1]);
}
int ask(int p,int l,int r,int ql,int qr){
	if(ql>qr)	return 0;
	if(l==ql&&r==qr)	return mx[p];
	if(qr<=mid)	return ask(p<<1,l,mid,ql,qr);
	else if(ql>mid)	return ask(p<<1|1,mid+1,r,ql,qr);
	else return max(ask(p<<1,l,mid,ql,mid),ask(p<<1|1,mid+1,r,mid+1,qr));
}
void dfs(int x,int fa){
	int pre=ask(1,1,m,a[x],a[x]);
	int val=max(ask(1,1,m,1,a[x]-1)+1,pre);
	res[x]=max(res[fa],val);	change(1,1,m,a[x],val);
	for(auto to:g[x])	if(to!=fa)	dfs(to,x);
	change(1,1,m,a[x],pre);
}
signed main(){
	cin>>n;
	for(int i=1;i<=n;i++)	scanf("%d",&a[i]),v.push_back(a[i]);
	for(int i=1,a,b;i<n;i++)	scanf("%d %d",&a,&b),add(a,b);
	sort(v.begin(),v.end()); v.erase(unique(v.begin(),v.end()),v.end()); m=v.size();
	for(int i=1;i<=n;i++)	a[i]=lower_bound(v.begin(),v.end(),a[i])-v.begin()+1;
	dfs(1,1);	
	for(int i=1;i<=n;i++)	printf("%d\n",res[i]);
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章