​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
*/