您的位置:首页 > 其它

Hdu 4718 The LCIS on the Tree 动态树 LCT

2014-11-06 23:00 417 查看


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 S1, S2, ... , SN, and a pair of integers (i, j), if 1 <= i <= j <= N and Si < Si+1 < Si+2 < ... < Sj-1 < Sj , then the sequence Si, Si+1,
... , Sj 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.



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 <= 105), the number of nodes in the tree.

The second line comes with N numbers v1, v2, v3 ... , vN, describing the value of node 1 to node N. (1 <= vi <= 109)

The third line comes with N - 1 numbers p2, p3, p4 ... , pN, 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 <= 105)

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.



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

2013 ACM/ICPC Asia Regional Online —— Warmup2



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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: