1 5 1 2 3 4 5 1 1 3 3 3 1 5 4 5 2 5
Case #1: 3 2 3
求路径上最长的连续递增子串的最大长度
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; }