Codeforces Round #279 (Div. 2) F. Treeland Tour (暴力枚举树链+LIS)

传送门

给定带点权的无根树,求出所有简单路径上最长的LIS。

O(N²logn)的做法:
枚举每个节点作为根节点开始dfs,每条链上作一个nlogn的dp .
dp[i]表示长度为i的LIS结尾的最小值
当a[i]>dp[len],dp[++len] = a[i]
否则二分找到a[i]可以代替的位置

记得回溯的时候要恢复成原先的值。

#include<bits/stdc++.h>
using namespace std;
//#pragma GCC optimize(2)
#define ull unsigned long long
#define ll long long
#define pii pair<int, int>
#define lc rt<<1
#define rc rt<<1|1
const int maxn = 6e3 + 10;
const ll mod = 998244353;
const ll inf = (ll)4e17+5;
const int INF = 1e9 + 7;
const double pi = acos(-1.0);
ll inv(ll b){
    
    if(b==1)return 1;return(mod-mod/b)*inv(mod%b)%mod;}
inline ll read()
{
    
    
    ll x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){
    
    if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){
    
    x=x*10+ch-'0';ch=getchar();}
    return x*f;
}

int a[maxn],n;
int dp[maxn],len;//长度为i的LIS 结尾元素最小值
vector<int> g[maxn];
int ans=1;//答案
void dfs(int rt,int fa) 
{
    
    
    for(int i:g[rt]) 
    {
    
    
        if(i==fa) continue;
        if(a[i]>dp[len]) 
		{
    
    
			ans=max(ans,len+1);
			dp[++len]=a[i];
			dfs(i,rt);
			len--;
		}
		else 
		{
    
    
			int idx=lower_bound(dp+1,dp+len+1,a[i])-dp;//idx∈[1,len]
			int v=dp[idx];
			dp[idx]=a[i];
			dfs(i,rt);
			dp[idx]=v;
		}
    }
}
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);
        g[u].push_back(v);
        g[v].push_back(u);
    }   
	for(int i=1;i<=n;i++)
	{
    
    
		dp[1]=a[i];
		len=1;
		dfs(i,0);
	}
    cout<<ans<<'\n';
    return 0;
}

贴一份n²logn的权值线段树tle的代码

#include<bits/stdc++.h>
using namespace std;
//#pragma GCC optimize(2)
#define ull unsigned long long
#define ll long long
#define pii pair<int, int>
#define lc rt<<1
#define rc rt<<1|1
const int maxn = 6e3 + 10;
const ll mod = 998244353;
const ll inf = (ll)4e17+5;
const int INF = 1e9 + 7;
const double pi = acos(-1.0);
ll inv(ll b){
    
    if(b==1)return 1;return(mod-mod/b)*inv(mod%b)%mod;}
inline ll read()
{
    
    
    ll x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){
    
    if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){
    
    x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
//对点权建树 维护以之结尾的最长的LIS
struct node 
{
    
    
    int mx;
    int l,r;
}tree[maxn<<2];
inline void pushup(int rt)
{
    
    
    tree[rt].mx=max(tree[lc].mx,tree[rc].mx);
}
inline void build(int rt,int l,int r) 
{
    
    
    tree[rt].mx=0;
    tree[rt].l=l,tree[rt].r=r;
    if(l==r) return;
    else 
    {
    
    
        int mid=l+r>>1;
        build(lc,l,mid);
        build(rc,mid+1,r);
    }
}
inline void upd(int rt,int pos,int v,bool f)
{
    
    
    int l=tree[rt].l,r=tree[rt].r;
    if(l==r) 
    {
    
    
        if(f)
            tree[rt].mx=max(tree[rt].mx,v);
        else tree[rt].mx=v;//直接赋值
        return ;
    }
    int mid=l+r>>1;
    if(pos<=mid) upd(lc,pos,v,f);
    else upd(rc,pos,v,f);
    pushup(rt); 
}
inline int qry(int rt,int vl,int vr)
{
    
    
    int l=tree[rt].l,r=tree[rt].r;
    if(vl>vr) return 0;
    if(vl<=l && r<=vr) return tree[rt].mx;
    int mid=l+r>>1;
    if(vr<=mid) return qry(lc,vl,vr);
    else if(vl>mid) return qry(rc,vl,vr);
    return max(qry(lc,vl,vr) , qry(rc,vl,vr));
}
int a[maxn];
vector<int> g[maxn];
int b[maxn],n0,n,idx[maxn];
int ans=1;//答案
void dfs(int rt,int fa) 
{
    
    
    for(int i:g[rt]) 
    {
    
    
        if(i==fa) continue;
        int t=qry(1,1,idx[i]-1);//严格小于 所以是idx[i]-1
        ans=max(ans,t+1);
        int last=qry(1,idx[i],idx[i]);
        upd(1,idx[i],t+1,1);
        dfs(i,rt);
        upd(1,idx[i],last,0);//回溯 消除影响变回之前的这个值
    }
}
int main()
{
    
    
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
    
    
        scanf("%d",a+i);
        b[i]=a[i];
    }
    sort(b+1,b+n+1);
    n0=unique(b+1,b+n+1)-b-1;
    for(int i=1;i<=n;i++) idx[i]=lower_bound(b+1,b+n0+1,a[i])-b;
    for(int i=1,u,v;i<n;i++)
    {
    
    
        scanf("%d %d",&u,&v);
        g[u].push_back(v);
        g[v].push_back(u);
    }   
    build(1,1,n0);
    for(int i=1;i<=n;i++)
    {
    
    
        upd(1,idx[i],1,1);
        dfs(i,i);
        upd(1,idx[i],0,0);
    }
    cout<<ans<<'\n';
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_46030630/article/details/120738729