题目链接:codeforces-490F
题目大意:
n个城市,n-1条边,任意两个城市都有路径到达。现在一个乐队开演唱会,乐队沿着一条路途径城市。
乐队每开一次演唱会,当前城市的人口数量一定要比之前开演唱会的城市的人口数量多。
每个城市的人口数量为ai,问乐队最多能在多少个城市开演唱会
其实就是求树上的最长上升子序列。
类似于nlogn的递增上升子序列算法。
代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <set>
#include<malloc.h>
#include <map>
#include <vector>
#include <stack>
#include <queue>
#define ri(n) scanf("%d",&n)
#define oi(n) printf("%d\n",n)
#define rl(n) scanf("%lld",&n)
#define ol(n) printf("%lld\n",n)
#define rep(i,l,r) for(i=l;i<=r;i++)
#define rep1(i,l,r) for(i=l;i<r;i++)
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int epg=10-8;
const int maxn=6000+10;
int a[maxn],d[maxn];
int n;
vector<int>g[maxn];
int ans=-inf;
void init()
{
for(int i=0; i<maxn; i++)
g[i].clear();
for(int i=0; i<n; i++)
d[i]=inf;
}
void dfs(int u,int f)
{
int tmp=lower_bound(d,d+n,a[u])-d;
ans=max(ans,tmp+1);
int t=d[tmp];
d[tmp]=a[u];
for(int i=0;i<g[u].size();i++)
{
if(g[u][i]==f)
continue;
dfs(g[u][i],u);
}
d[tmp]=t;
}
int main()
{
//int n;
while(scanf("%d",&n)==1)
{
init();
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=1; i<n; i++)
{
int u,v;
scanf("%d%d",&u,&v);
g[u].push_back(v);
g[v].push_back(u);
}
for(int i=1; i<=n; i++)
dfs(i,0);
printf("%d\n",ans);
}
return 0;
}