It is also an LCT. Write it to deepen your understanding of LCT. The pitfall of this question lies in that it is too pitfall. The question is the longest continuously rising substring in the tree path, which tests how to maintain it. The idea at the beginning was to maintain the three variables ls, RS, and mxl, which indicate the longest increase from left to right, the longest increase from right to end, and the longest increase in total, the longest increase is possible under the following conditions,
Mxl = max (CH [0]-> mxl, CH [1]-> mxl) and
Make temp = 1 store left and right lval, rval,
If Val> CH [0]-> rval temp + = CH [0]-> rs
If Val <ch [1]-> lval temp + = CH [1]-> ls
However, because the path must be transferred to the root, and the interval must have a flip mark when the root is switched, you must maintain the information and know the longest drop LD from left to right, and the longest drop rd from right to end, and the maximum decrease in the interval mxd. you can:
Swap (lval, rval) Swap (LS, RD) Swap (RS, LD) Swap (mxl, mxd ).
However, we have to deal with all kinds of null, so the question is very much about how to write this UPD function. Anyway, I wrote 100 lines in UPD .. My heart is broken...
#pragma warning(disable:4996)#include <iostream>#include <cstring>#include <string>#include <vector>#include <cmath>#include <cstdio>#include <algorithm>using namespace std;#define ll long long#define maxn 150000#define INF 1500000000#define NINF -1struct Node{Node *p, *ch[2];bool rev;int val,size;int lval, rval;int ls, rs, mxl;int ld, rd, mxd;bool isRoot;Node *fa;Node(){val = 0;size = 0;ls = rs = mxl = 0;ld = rd = mxd = 0;lval = INF; rval = NINF;isRoot = 0;}void setc(Node *c, int d){ch[d] = c;c->p = this;}bool d(){return p->ch[1] == this;}void upd();void relax();void revIt();void setRoot(Node *f);}Tnull,*null=&Tnull;void Node::upd(){size = ch[0]->size + ch[1]->size + 1;lval = ch[0] != null ? ch[0]->lval : val;rval = ch[1] != null ? ch[1]->rval : val;if (ch[0] == null){if (ch[1] == null) ls = ld = 1;else{ls = 1; ld = 1;if (val < ch[1]->lval) ls += ch[1]->ls;if (val > ch[1]->lval) ld += ch[1]->ld;}}else{if (ch[0]->ls == ch[0]->size){ls = ch[0]->size;if (ch[0]->rval < val){ls += 1;if (val < ch[1]->lval){ls += ch[1]->ls;}}}else{ls = ch[0]->ls;}if (ch[0]->ld == ch[0]->size){ld = ch[0]->size;if (ch[0]->rval > val){ld += 1;if (val > ch[1]->lval){ld += ch[1]->ld;}}}else {ld = ch[0]->ld;}}if (ch[1] == null){if (ch[0] == null) rd = rs = 1;else{rd = rs = 1;if (val > ch[0]->rval) rs += ch[0]->rs;if (val < ch[0]->rval) rd += ch[0]->rd;}}else{if (ch[1]->rs == ch[1]->size){rs = ch[1]->size;if (val < ch[1]->lval){rs += 1;if (val>ch[0]->rval){rs += ch[0]->rs;}}}else{rs = ch[1]->rs;}if (ch[1]->rd == ch[1]->size){rd = ch[1]->size;if (val > ch[1]->lval){rd += 1;if (val < ch[0]->rval){rd += ch[0]->rd;}}}else{rd = ch[1]->rd;}}mxl = max(ch[0]->mxl, ch[1]->mxl);mxd = max(ch[0]->mxd, ch[1]->mxd);int temp = 1;if (ch[0] != null&&val > ch[0]->rval) temp += ch[0]->rs;if (ch[1] != null&&val < ch[1]->lval) temp += ch[1]->ls;mxl = max(mxl, temp);temp = 1;if (ch[0] != null&&val < ch[0]->rval) temp += ch[0]->rd;if (ch[1] != null&&val>ch[1]->lval) temp += ch[1]->ld;mxd = max(mxd, temp);}void Node::revIt(){swap(ch[0], ch[1]);swap(lval, rval);swap(ls, rd);swap(rs, ld);swap(mxl, mxd);rev ^= 1;}void Node::setRoot(Node *f){fa = f;isRoot = true;p = null;}void Node::relax(){if (rev){for (int i = 0; i < 2; i++){if (ch[i] != null) ch[i]->revIt();}rev = 0;}}Node mem[maxn], *C = mem;Node *make(int v){C->lval = C->rval = C->val = v;C->ls = C->rs = C->mxl = 1;C->ld = C->rd = C->mxd = 1;C->rev = 0;C->ch[0] = C->ch[1] = null;C->isRoot = true;C->p = C->fa = null;return C++;}void rot(Node *t){Node *p = t->p;p->relax();t->relax();bool d = t->d();p->p->setc(t, p->d());p->setc(t->ch[!d], d);t->setc(p, !d);p->upd();if (p->isRoot){p->isRoot = false;t->isRoot = true;t->fa = p->fa;}}void pushTo(Node *t){static Node *stk[maxn];int top = 0;while (t != null){stk[top++] = t;t = t->p;}for (int i = top - 1; i >= 0; i--)stk[i]->relax();}void splay(Node *u, Node *f = null){pushTo(u);while (u->p != f){if (u->p->p == f)rot(u);else u->d() == u->p->d() ? (rot(u->p), rot(u)) : (rot(u), rot(u));}u->upd();}Node *v[maxn];vector<int> G[maxn];int n, nQ;int que[maxn], fa[maxn], qh = 0, qt = 0;int wht[maxn];void bfs(){qh = qt = 0;que[qt++] = 1;while (qh < qt){int u = que[qh++]; int e;for (int i = 0; i < G[u].size(); i++){e = G[u][i];if (e != fa[u]){v[e]->fa = v[u]; que[qt++] = e;}}}}Node *expose(Node *u){Node *v;for (v = null; u != null; v = u, u = u->fa){splay(u);u->ch[1]->setRoot(u);u->setc(v, 1);v->fa = u;}return v;}void makeRoot(Node *u){expose(u);splay(u);u->revIt();}int main(){int T; cin >> T; int ca = 0;while (T--){scanf("%d", &n);C = mem;for (int i = 1; i <= n; i++){scanf("%d", wht + i);v[i] = make(wht[i]);G[i].clear();}fa[1] = -1; int ti;for (int i = 2; i <= n; i++){scanf("%d", &ti);fa[i] = ti;G[i].push_back(ti); G[ti].push_back(i);}bfs();scanf("%d", &nQ); int ui, vi;Node *nu, *nv;printf("Case #%d:\n", ++ca);for (int i = 0; i < nQ; i++){scanf("%d%d", &ui, &vi);nu = v[ui]; nv = v[vi];makeRoot(nu);expose(nv);splay(nv);printf("%d\n", nv->mxl);}if (T != 0) puts("");}return 0;}