hdu 4718 The LCIS on the Tree

Posted lmissher

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu 4718 The LCIS on the Tree相关的知识,希望对你有一定的参考价值。

题意给你q次询问,给一条链问从给定起点到给定终点的最长连续严格递增子序列。

 

因为给定起点与终点所以路径可能与dfs序的树节点展开顺序相反。所以问题变成了给n个数询问一个区间的最长LCIS。

但因为方向可正可负,所以我们除了维护区间的最长递增以外还要维护最长递减。线段树的部分就做完了。

 

树链剖分的时候进行线段树合并,合并的时候右区间取前一个区间,左区间取当前区间。要注意从起点出发的链取最长递减,从终点出发的取最长递增。

当他们来到一条链时,当x比y 的深度更浅这时应该将这段长度与y合并,y比x浅时应该将长度与x合并。因为链都是向上合并的,不能向下合并。

 

最后将起点的最长递减与终点的最长递增比较,如果起点合并后的左端点小于终点合并后的左端点就将起点区间的左长度与终点区间的左长度加起来更新答案。

 

对拍大法好!!

 

技术分享图片
#include <bits/stdc++.h>
#define Lson l,mid,rt<<1
#define Rson mid+1,r,rt<<1|1
using namespace std;
const int M = 1e5+7;
int _,n,q,a[M];
int head[M],cnt,tot,tmp,cas=1;
int sz[M],f[M],dep[M],son[M],rnk[M],top[M],id[M];
struct edge
{
    int v,next;
}e[M<<1];
struct Tree
{
    int len;
    int lnum,rnum;
    int inl,inr,in;
    int del,der,de;
}tree[M<<3];
void init(){
    cnt=tot=0;memset(head,-1,sizeof(head));
}
void add(int u,int v){
    e[++cnt].v=v;e[cnt].next=head[u];
    head[u]=cnt;
}
void dfs(int u,int fa,int d){
    sz[u]=1;son[u]=-1;f[u]=fa;dep[u]=d;
    for(int i=head[u];~i;i=e[i].next){
        int v=e[i].v;
        if(v==fa) continue;
        dfs(v,u,d+1);
        sz[u]+=sz[v];
        if(son[u]==-1||sz[v]>sz[son[u]]) son[u]=v;
    }
    return ;
}
void dfs1(int u,int t){
    id[u]=++tot;
    rnk[tot]=u;
    top[u]=t;
    if(son[u]==-1) return ;
    dfs1(son[u],t);
    for(int i=head[u];~i;i=e[i].next){
        int v=e[i].v;
        if(v==f[u]||v==son[u]) continue;
        dfs1(v,v);
    }
    return ;
}
void Pushup(int rt,int l,int r){
    tree[rt].len=tree[l].len+tree[r].len;
    tree[rt].lnum=tree[l].lnum;
    tree[rt].rnum=tree[r].rnum;
    tree[rt].inl=tree[l].inl;
    tree[rt].inr=tree[r].inr;
    tree[rt].in=max(tree[l].in,tree[r].in);
    tree[rt].del=tree[l].del;
    tree[rt].der=tree[r].der;
    tree[rt].de=max(tree[l].de,tree[r].de);
    if(tree[l].rnum<tree[r].lnum){
        if(tree[l].inl==tree[l].len) tree[rt].inl+=tree[r].inl;
        tree[rt].in=max(tree[rt].in,tree[rt].inl);
        if(tree[r].inr==tree[r].len) tree[rt].inr+=tree[l].inr;
        tree[rt].in=max(tree[rt].in,tree[rt].inr);
        tree[rt].in=max(tree[rt].in,tree[l].inr+tree[r].inl);
    }
    if(tree[l].rnum>tree[r].lnum){
        if(tree[l].del==tree[l].len) tree[rt].del+=tree[r].del;
        tree[rt].de=max(tree[rt].de,tree[rt].del);
        if(tree[r].der==tree[r].len) tree[rt].der+=tree[l].der;
        tree[rt].de=max(tree[rt].de,tree[rt].der);
        tree[rt].de=max(tree[rt].de,tree[l].der+tree[r].del);
    }
}
void build(int l,int r,int rt){
    if(l==r){
        tree[rt].lnum=tree[rt].rnum=a[rnk[l]];tree[rt].len=1;
        tree[rt].inl=tree[rt].inr=tree[rt].del=tree[rt].der=tree[rt].de=tree[rt].in=1;
        return;
    }
    int mid=(l+r)>>1;
    build(Lson);
    build(Rson);
    Pushup(rt,rt<<1,rt<<1|1);
}
int query(int L,int R,int l,int r,int rt){
    if(L==l&&r==R){
        return rt;
    }
    int mid=(l+r)>>1;
    if(L>mid) return query(L,R,Rson);
    else if(R<=mid) return query(L,R,Lson);
    else{
        int ll=query(L,mid,Lson),rr=query(mid+1,R,Rson);
        Pushup(++tmp,ll,rr);
        return tmp;
    }
}
int sum(int x,int y){
    int fx=top[x],fy=top[y];tmp=M<<2;
    int xl,xr=-1,yl,yr=-1;
    while(fx!=fy){
        if(dep[fx]>dep[fy]){
            xl=query(id[fx],id[x],1,n,1);
            if(xr==-1) xr=xl;
            else{
                Pushup(++tmp,xl,xr);xr=tmp;
            }
            x=f[fx],fx=top[x];
        }
        else{
            yl=query(id[fy],id[y],1,n,1);
            //cout<<tree[yl].lnum<<endl;
            if(yr==-1) yr=yl;
            else{
                Pushup(++tmp,yl,yr);yr=tmp;
            }
            y=f[fy],fy=top[y];
        }
        //cout<<fx<<" "<<fy<<" "<<tree[yr].de<<endl;
    }
    if(dep[x]<dep[y]){
        yl=query(id[x],id[y],1,n,1);
        if(yr==-1) yr=yl;
        else{
            Pushup(++tmp,yl,yr);yr=tmp;
        }
    }
    else{
        xl=query(id[y],id[x],1,n,1);
        if(xr==-1) xr=xl;
        else{
            Pushup(++tmp,xl,xr);xr=tmp;
        }
    }
    if(xr==-1) return tree[yr].in;
    if(yr==-1) return tree[xr].de;
    int res;
    //cout<<tree[xr].de<<" "<<tree[yr].in<<endl;
    res=max(tree[xr].de,tree[yr].in);
    if(tree[xr].lnum<tree[yr].lnum){
        res=max(res,tree[xr].del+tree[yr].inl);
    }
    return res;
}
int main(){
    scanf("%d",&_);
    while(_--){
        init();
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        for(int i=2;i<=n;i++){
            int u;
            scanf("%d",&u);
            add(u,i);add(i,u);
        }
        dfs(1,-1,1);dfs1(1,1);
        build(1,n,1);
        scanf("%d",&q);
        printf("Case #%d:
",cas++);
        while(q--){
            int from,to;
            scanf("%d%d",&from,&to);
            printf("%d
",sum(from,to));
        }
        if(_) printf("
");
    }
    return 0;
}
View Code

 

以上是关于hdu 4718 The LCIS on the Tree的主要内容,如果未能解决你的问题,请参考以下文章

POJ 4718 /// 树链剖分+线段树区间合并 求树上两点间的LCIS长度

HDU 4836 The Query on the Tree lca || 欧拉序列 || 动态树

HDU 4836 The Query on the Tree lca || 欧拉序列 || 动态树

[hdu4010]: Query on The Trees

Hdu 4010-Query on The Trees LCT,动态树

hdu4916 Count on the path