The LCIS on the Tree HDU - 4718

http://acm.hdu.edu.cn/showproblem.php?pid=4718

链上LCIS 用区间合并解决 线段树每次查询都带回该区间内的左值 右值 左连续段 右连续段 最大连续段 然后和该链上的上一次查询合并 这里直接当做线段树区间合并的法子写的 uv两点顺着两条链向上爬 会师后特殊处理即可

7000+的代码 debug一天。。 爬链时开了很多没用的变量 反正多了没错。。

#include <bits/stdc++.h>
using namespace std;
#define N 0x3f3f3f3f

struct node1
{
    int v;
    int next;
};

struct node2//0 up   1 down
{
    int l;
    int r;
    int lval;
    int rval;
    int left0;
    int right0;
    int all0;
    int left1;
    int right1;
    int all1;
};

node1 edge[200010];
node2 tree[400010];
int val[100010],first[100010],fa[100010],deep[100010],sum[100010],son[100010],top[100010],mp1[100010],mp2[100010];
int n,q,num;

void addedge(int u,int v)
{
    edge[num].v=v;
    edge[num].next=first[u];
    first[u]=num++;
}

void dfsI(int cur)
{
    int i,v;
    sum[cur]=1,son[cur]=-1;
    for(i=first[cur];i!=-1;i=edge[i].next)
    {
        v=edge[i].v;
        if(v!=fa[cur])
        {
            fa[v]=cur,deep[v]=deep[cur]+1;
            dfsI(v);
            sum[cur]+=sum[v];
            if(son[cur]==-1||sum[son[cur]]<sum[v])
            {
                son[cur]=v;
            }
        }
    }
}

void dfsII(int cur,int tp)
{
    int i,v;
    num++;
    top[cur]=tp,mp1[cur]=num,mp2[num]=cur;
    if(son[cur]==-1) return;
    dfsII(son[cur],tp);
    for(i=first[cur];i!=-1;i=edge[i].next)
    {
        v=edge[i].v;
        if(v!=fa[cur]&&v!=son[cur])
        {
            dfsII(v,v);
        }
    }
}

void pushup(int cur)
{
    tree[cur].lval=tree[2*cur].lval,tree[cur].rval=tree[2*cur+1].rval;

    tree[cur].left0=tree[2*cur].left0;
    if(tree[cur].left0==tree[2*cur].r-tree[2*cur].l+1&&tree[2*cur].rval<tree[2*cur+1].lval) tree[cur].left0+=tree[2*cur+1].left0;
    tree[cur].right0=tree[2*cur+1].right0;
    if(tree[cur].right0==tree[2*cur+1].r-tree[2*cur+1].l+1&&tree[2*cur].rval<tree[2*cur+1].lval) tree[cur].right0+=tree[2*cur].right0;
    tree[cur].all0=max(tree[2*cur].all0,tree[2*cur+1].all0);
    if(tree[2*cur].rval<tree[2*cur+1].lval) tree[cur].all0=max(tree[cur].all0,tree[2*cur].right0+tree[2*cur+1].left0);

    tree[cur].left1=tree[2*cur].left1;
    if(tree[cur].left1==tree[2*cur].r-tree[2*cur].l+1&&tree[2*cur].rval>tree[2*cur+1].lval) tree[cur].left1+=tree[2*cur+1].left1;
    tree[cur].right1=tree[2*cur+1].right1;
    if(tree[cur].right1==tree[2*cur+1].r-tree[2*cur+1].l+1&&tree[2*cur].rval>tree[2*cur+1].lval) tree[cur].right1+=tree[2*cur].right1;
    tree[cur].all1=max(tree[2*cur].all1,tree[2*cur+1].all1);
    if(tree[2*cur].rval>tree[2*cur+1].lval) tree[cur].all1=max(tree[cur].all1,tree[2*cur].right1+tree[2*cur+1].left1);
}

void build(int l,int r,int cur)
{
    int m;
    tree[cur].l=l;
    tree[cur].r=r;
    if(l==r)
    {
        tree[cur].lval=val[mp2[l]];
        tree[cur].rval=val[mp2[l]];
        tree[cur].left0=1;
        tree[cur].right0=1;
        tree[cur].all0=1;
        tree[cur].left1=1;
        tree[cur].right1=1;
        tree[cur].all1=1;
        return;
    }
    m=(l+r)/2;
    build(l,m,2*cur);
    build(m+1,r,2*cur+1);
    pushup(cur);
}

void queryII(int pl,int pr,int op,int &lval,int &rval,int &left,int &right,int &all,int cur)
{
    int llval,lrval,lleft,lright,lall;
    int rlval,rrval,rleft,rright,rall;
    //printf("%d %d %d %d\n",pl,pr,tree[cur].l,tree[cur].r);
    if(pl==tree[cur].l&&tree[cur].r==pr)//
    {
        lval=tree[cur].lval;
        rval=tree[cur].rval;
        if(op==0)
        {
            left=tree[cur].left0;
            right=tree[cur].right0;
            all=tree[cur].all0;
        }
        else
        {
            left=tree[cur].left1;
            right=tree[cur].right1;
            all=tree[cur].all1;
        }
        //printf("gou: %d %d %d %d\n",pl,pr,lval,rval);
        return;
    }
    if(pr<=tree[2*cur].r)
    {
        queryII(pl,pr,op,lval,rval,left,right,all,2*cur);
    }
    else if(pl>=tree[2*cur+1].l)
    {
        queryII(pl,pr,op,lval,rval,left,right,all,2*cur+1);
    }
    else
    {
        queryII(pl,tree[2*cur].r,op,llval,lrval,lleft,lright,lall,2*cur);
        queryII(tree[2*cur+1].l,pr,op,rlval,rrval,rleft,rright,rall,2*cur+1);
        lval=llval,rval=rrval;
        left=lleft;
        if(op==0&&left==tree[2*cur].r-pl+1&&lrval<rlval) left+=rleft;
        else if(op==1&&left==tree[2*cur].r-pl+1&&lrval>rlval) left+=rleft;
        right=rright;
        if(op==0&&right==pr-tree[2*cur+1].l+1&&lrval<rlval) right+=lright;
        else if(op==1&&right==pr-tree[2*cur+1].l+1&&lrval>rlval) right+=lright;
        all=max(lall,rall);
        if(op==0&&lrval<rlval) all=max(all,lright+rleft);
        else if(op==1&&lrval>rlval) all=max(all,lright+rleft);
    }
}

int queryI(int u,int v)
{
    int res;
    int lval0,rval0,left0,right0,all0,plval0,prval0,pleft0,pright0,pall0,tlval0,trval0,tleft0,tright0,tall0;
    int lval1,rval1,left1,right1,all1,plval1,prval1,pleft1,pright1,pall1,tlval1,trval1,tleft1,tright1,tall1;
    res=0,plval1=N,plval0=-N,pleft0=0,pleft1=0;
    while(top[u]!=top[v])
    {
        if(deep[top[u]]>deep[top[v]])
        {
            queryII(mp1[top[u]],mp1[u],1,lval1,rval1,left1,right1,all1,1);
            //printf("#1u %d %d\n",mp1[top[u]],mp1[u]);
            //printf("#1u %d %d %d %d %d\n",lval1,rval1,left1,right1,all1);
            res=max(res,all1);
            if(rval1>plval1) res=max(res,right1+pleft1);
            if(left1==mp1[u]-mp1[top[u]]+1&&rval1>plval1) pleft1=left1+pleft1;
            else pleft1=left1;
            res=max(res,pleft1);
            plval1=lval1;
            u=fa[top[u]];
        }
        else
        {
            queryII(mp1[top[v]],mp1[v],0,lval0,rval0,left0,right0,all0,1);
            //printf("#1v %d %d\n",mp1[top[v]],mp1[v]);
            //printf("#1v %d %d %d %d %d\n",lval0,rval0,left0,right0,all0);
            res=max(res,all0);
            if(rval0<plval0) res=max(res,right0+pleft0);
            if(left0==mp1[v]-mp1[top[v]]+1&&rval0<plval0) pleft0=left0+pleft0;
            else pleft0=left0;
            res=max(res,pleft0);
            plval0=lval0;
            v=fa[top[v]];
        }
    }
    if(deep[u]>deep[v])
    {
        queryII(mp1[v],mp1[u],1,lval1,rval1,left1,right1,all1,1);
        //printf("#2u %d %d %d %d %d\n",lval1,rval1,left1,right1,all1);
        res=max(res,all1);
        if(rval1>plval1) res=max(res,right1+pleft1);
        if(left1==mp1[u]-mp1[v]+1&&rval1>plval1) pleft1=left1+pleft1;
        else pleft1=left1;
        res=max(res,pleft1);
        plval1=lval1;
        //printf("%d %d %d\n",plval0,pleft1,pleft0);
        if(plval1<plval0) res=max(res,pleft1+pleft0);
    }
    else
    {
        queryII(mp1[u],mp1[v],0,lval0,rval0,left0,right0,all0,1);
        //printf("#2v %d %d %d %d %d\n",lval0,rval0,left0,right0,all0);
        res=max(res,all0);
        if(rval0<plval0) res=max(res,right0+pleft0);
        if(left0==mp1[v]-mp1[u]+1&&rval0<plval0) pleft0=left0+pleft0;
        else pleft0=left0;
        res=max(res,pleft0);
        plval0=lval0;
        //printf("%d %d %d\n",plval0,pleft1,pleft0);
        if(plval1<plval0) res=max(res,pleft1+pleft0);
    }
    return res;
}

int main()
{
    int t,cas,i,u,v;
    scanf("%d",&t);
    for(cas=1;cas<=t;cas++)
    {
        scanf("%d",&n);
        for(i=1;i<=n;i++)
        {
            scanf("%d",&val[i]);
        }
        memset(first,-1,sizeof(first));
        num=0;
        for(i=2;i<=n;i++)
        {
            scanf("%d",&u);
            addedge(u,i);
            addedge(i,u);
        }
        fa[1]=-1,deep[1]=1;
        dfsI(1);
        num=0;
        dfsII(1,1);
        build(1,n,1);
        printf("Case #%d:\n",cas);
        scanf("%d",&q);
        while(q--)
        {
            scanf("%d%d",&u,&v);
            printf("%d\n",queryI(u,v));
        }
        if(cas<t) printf("\n");
    }
    return 0;
}

/*
100
10
1 2 3 4 5 6 7 8 9 10
  6 2 5 1 5 1 7 10 4
*/

猜你喜欢

转载自blog.csdn.net/sunyutian1998/article/details/81544301