The LCIS on the Tree
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others)Total Submission(s): 533 Accepted Submission(s): 167
Problem Description
For a sequence S
1, S
2, ... , S
N, and a pair of integers (i, j), if 1 <= i <= j <= N and S
i < S
i+1 < S
i+2 < ... < S
j-1 < S
j , then the sequence S
i, S
i+1, ... , S
j is a
CIS(Continuous Increasing Subsequence). The longest
CIS of a sequence is called the
LCIS (Longest Continuous Increasing Subsequence).
Now we consider a tree rooted at node 1. Nodes have values. We have Q queries, each with two nodes u and v. You have to find the shortest path from u to v. And write down each nodes' value on the path, from u to v, inclusive. Then you will get a sequence, and please show us the length of its LCIS.
Now we consider a tree rooted at node 1. Nodes have values. We have Q queries, each with two nodes u and v. You have to find the shortest path from u to v. And write down each nodes' value on the path, from u to v, inclusive. Then you will get a sequence, and please show us the length of its LCIS.
Input
The first line has a number T (T <= 10) , indicating the number of test cases.
For each test case, the first line is a number N (N <= 10 5), the number of nodes in the tree.
The second line comes with N numbers v1, v2, v3 ... , v N, describing the value of node 1 to node N. (1 <= v i <= 10 9)
The third line comes with N - 1 numbers p 2, p 3, p 4 ... , p N, describing the father nodes of node 2 to node N. Node 1 is the root and will have no father.
Then comes a number Q, it is the number of queries. (Q <= 10 5)
For next Q lines, each with two numbers u and v. As described above.
For each test case, the first line is a number N (N <= 10 5), the number of nodes in the tree.
The second line comes with N numbers v1, v2, v3 ... , v N, describing the value of node 1 to node N. (1 <= v i <= 10 9)
The third line comes with N - 1 numbers p 2, p 3, p 4 ... , p N, describing the father nodes of node 2 to node N. Node 1 is the root and will have no father.
Then comes a number Q, it is the number of queries. (Q <= 10 5)
For next Q lines, each with two numbers u and v. As described above.
Output
For test case X, output "Case #X:" at the first line.
Then output Q lines, each with an answer to the query.
There should be a blank line *BETWEEN* each test case.
Then output Q lines, each with an answer to the query.
There should be a blank line *BETWEEN* each test case.
Sample Input
1 5 1 2 3 4 5 1 1 3 3 3 1 5 4 5 2 5
Sample Output
Case #1: 3 2 3
Source
Recommend
zhuyuanchen520 | We have carefully selected several similar problems for you:
5099
5098
5097
5096
5095
求路径上最长的连续递增子串的最大长度
splay维护这样一个东西
最左边的值,最右边的值
最左边连续上升长度,最左边连续下降长度
最右边连续上升长度,最右边连续下降长度
区间最长上升子串长,区间最长下降子串长
区间大小
然后update的时候比较麻烦~~~是三个结点的合并,线段树的话两个结点就行了
反正是要么是左右孩子的值中的最值,两颗子树和根是可以连起来的
我写的比较费劲~
#pragma comment(linker, "/STACK:102400000,102400000")
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
#define maxn 500007
struct Node{
Node *fa,*ch[2];
bool rev,root;
int val,size;
int ulenl,ulenr,uans;
int dlenl,dlenr,dans;
int lnum,rnum;
};
Node pool[maxn];
Node *nil,*tree[maxn];
int cnt = 0;
void init(){
cnt = 1;
nil = tree[0] = pool;
nil->ulenl = nil->dlenl = nil->ulenr = nil->dlenr = 0;
nil->uans = nil->dans = 0;
nil->size = 0;
}
inline Node *newnode(int val,Node *f){
pool[cnt].fa = f;
pool[cnt].ch[0] = pool[cnt].ch[1] = nil;
pool[cnt].rev = false;
pool[cnt].root = true;
pool[cnt].rnum = val;
pool[cnt].lnum = val;
pool[cnt].val = val;
pool[cnt].ulenl = 1;
pool[cnt].ulenr = 1;
pool[cnt].uans = 1;
pool[cnt].dlenl = 1;
pool[cnt].dlenr = 1;
pool[cnt].dans = 1;
pool[cnt].size = 1;
return &pool[cnt++];
}
//splay向上更新信息
void update(Node *x){
Node *l = x->ch[0],*r = x->ch[1];
x->size = l->size + 1;
x->rnum = x->lnum = x->val;
x->ulenl = x->ulenr = x->dlenl = x->dlenr = 1;
x->uans = x->dans = 1;
if(l != nil){
if(x->val > l->rnum) x->ulenr = l->ulenr+1;
if(x->val < l->rnum) x->dlenr = l->dlenr+1;
if((l->ulenl == l->size) && x->val > l->rnum) x->ulenl = l->ulenl+1;
else x->ulenl = l->ulenl;
if((l->dlenl == l->size) && x->val < l->rnum) x->dlenl = l->dlenl+1;
else x->dlenl = l->dlenl;
x->uans = max(x->uans,l->uans);
x->dans = max(x->dans,l->dans);
x->lnum = l->lnum;
}
x->uans = max(x->uans,x->ulenl);
x->uans = max(x->uans,x->ulenr);
x->dans = max(x->dans,x->dlenl);
x->dans = max(x->dans,x->dlenr);
if(r != nil){
if(x->rnum < r->lnum) x->uans = max(x->uans,x->ulenr+r->ulenl);
if(x->rnum > r->lnum) x->dans = max(x->dans,x->dlenr+r->dlenl);
if(x->rnum < r->lnum && (x->ulenl == x->size)) x->ulenl += r->ulenl;
if(x->rnum > r->lnum && (x->dlenl == x->size)) x->dlenl += r->dlenl;
if(x->rnum < r->lnum && (r->ulenr == r->size)) x->ulenr += r->ulenr;
else x->ulenr = r->ulenr;
if(x->rnum > r->lnum && (r->dlenr == r->size)) x->dlenr += r->dlenr;
else x->dlenr = r->dlenr;
x->uans = max(x->uans,r->uans);
x->dans = max(x->dans,r->dans);
x->rnum = r->rnum;
}
x->size += r->size;
x->uans = max(x->uans,x->ulenl);
x->uans = max(x->uans,x->ulenr);
x->dans = max(x->dans,x->dlenl);
x->dans = max(x->dans,x->dlenr);
//cout<<x->dans<<" "<<x->uans<<endl;
}
void update_rev(Node *x){
if(x == nil) return ;
x->rev = !x->rev;
swap(x->ch[0],x->ch[1]);
swap(x->rnum, x->lnum);
swap(x->ulenl,x->dlenr);
swap(x->dlenl,x->ulenr);
swap(x->uans, x->dans);
}
//splay下推信息
void pushdown(Node *x){
if(x->rev != false){
update_rev(x->ch[0]);
update_rev(x->ch[1]);
x->rev = false;
}
}
//splay在root-->x的路径下推信息
void push(Node *x){
if(!x->root) push(x->fa);
pushdown(x);
}
//将结点x旋转至splay中父亲的位置
void rotate(Node *x){
Node *f = x->fa, *ff = f->fa;
int t = (f->ch[1] == x);
if(f->root) x->root = true, f->root = false;
else ff->ch[ff->ch[1] == f] = x;
x->fa = ff;
f->ch[t] = x->ch[t^1];
x->ch[t^1]->fa = f;
x->ch[t^1] = f;
f->fa = x;
update(f);
}
//将结点x旋转至x所在splay的根位置
void splay(Node *x){
push(x);
Node *f, *ff;
while(!x->root){
f = x->fa,ff = f->fa;
if(!f->root)
if((ff->ch[1] == f) && (f->ch[1] == x)) rotate(f);
else rotate(x);
rotate(x);
}
update(x);
}
//将x到树根的路径并成一条path
Node *access(Node *x){
Node *y = nil;
while(x != nil){
splay(x);
x->ch[1]->root = true;
(x->ch[1] = y)->root = false;
update(x);
y = x;
x = x->fa;
}
return y;
}
//将结点x变成树根
void be_root(Node *x){
access(x);
splay(x);
update_rev(x);
}
struct Edge{
int v,next;
};
Edge edge[2*maxn];
int head[maxn],ecnt;
int value[maxn];
void add_edge(int u,int v){
edge[ecnt].v = v;
edge[ecnt].next = head[u];
head[u] = ecnt++;
edge[ecnt].v = u;
edge[ecnt].next = head[v];
head[v] = ecnt++;
}
void dfs(int u,int f){
tree[u] = newnode(value[u],tree[f]);
for(int i = head[u]; i != -1;i = edge[i].next){
if(edge[i].v == f) continue;
dfs(edge[i].v,u);
}
}
int main(){
int t,tt=0,n,w,x,y,v,q;
Node*p;
scanf("%d",&t);
while(t--){
if(tt > 0)printf("\n");
printf("Case #%d:\n",++tt);
scanf("%d",&n);
memset(head,-1,sizeof(head));
ecnt = 0;
init();
for(int i = 1;i <= n; i++)
scanf("%d",&value[i]);
for(int i = 2; i <= n; i++){
scanf("%d",&y);
add_edge(i,y);
}
dfs(1,0);
scanf("%d",&q);
while(q--){
scanf("%d%d",&x,&y);
be_root(tree[x]);
p = access(tree[y]);
printf("%d\n",p->uans);
}
}
return 0;
}