树上最长上升子序列

来源:互联网 发布:网络扑克有挂没 编辑:程序博客网 时间:2024/06/03 13:17

题目链接: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;}