HDU5052 Yaoge’s maximum profit(LCT)
典型的LCT操作,但是维护的是一个序列最左边减最右边的最小值,所以要维护左边减右边的最小值del[0]和一个右边减左边的最小值del[1](因为rev标记swap的时候对应的值也要交换)。维护的时候del[0]可能是来自于左右儿子的del[0],也有可能是来自于左儿子的最小值减去右儿子及当前节点的值的最大值,还有就是当前节点减去右儿子的最大值,比赛的时候漏了当前节点减去右儿子的最大值因而WA了。。- -0
#pragma warning(disable:4996) #include <iostream> #include <cstring> #include <string> #include <cstdio> #include <vector> #include <algorithm> #include <map> #include <assert.h> using namespace std; #define ll long long #define maxn 200000 #define INF 0x3f3f3f3f struct Node { Node *p, *ch[2]; bool rev; int val; int mx, mi; int add; int del[2]; int size; bool isRoot; Node *fa; Node(){ val = 0; rev = 0; mx = -INF; mi = INF; del[0] = del[1] = 0; add = 0; size = 0; } void setc(Node *c, int d){ ch[d] = c; c->p = this; } bool d(){ return p->ch[1] == this; } void upd(){ size = ch[0]->size + ch[1]->size + 1; mx = max(max(ch[0]->mx, ch[1]->mx), val); mi = min(min(ch[0]->mi, ch[1]->mi), val); del[0] = min(ch[0]->del[0], ch[1]->del[0]); del[0] = min(del[0], ch[0]->mi - max(val, ch[1]->mx)); del[0] = min(del[0], val - ch[1]->mx); del[1] = min(ch[0]->del[1], ch[1]->del[1]); del[1] = min(del[1], ch[1]->mi - max(val, ch[0]->mx)); del[1] = min(del[1], val - ch[0]->mx); } void revIt(){ swap(ch[0], ch[1]); swap(del[0], del[1]); rev ^= 1; } void addIt(int vx){ add += vx; val += vx; mx += vx; mi += vx; } void relax(); void setRoot(Node *f); }Tnull, *null = &Tnull; void Node::setRoot(Node *f){ fa = f; isRoot = true; p = null; } void Node::relax(){ if (add != 0){ for (int i = 0; i < 2; i++){ if (ch[i] != null) ch[i]->addIt(add); } add = 0; } 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->val = v; C->mx = C->mi = v; C->del[0] = C->del[1] = 0; C->rev = 0; C->add = 0; C->ch[0] = C->ch[1] = null; C->isRoot = true; C->p = null; 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> E[maxn]; int n, nQ; int que[maxn], fa[maxn], qh = 0, qt = 0; int wht[maxn]; void bfs() { qh = qt = 0; que[qt++] = 1; fa[1] = -1; while (qh < qt){ int u = que[qh++]; for (int i = 0; i < E[u].size(); i++){ int e = E[u][i]; if (e != fa[u]){ fa[e] = 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(); } void addPath(Node *u, Node *v, int ax) { makeRoot(u); expose(v); splay(v); v->addIt(ax); } int deltaPath(Node *u, Node *v) { makeRoot(u); expose(v); splay(v); return v->del[0]; } int main() { int T; cin >> T; while (T--){ C = mem; scanf("%d", &n); for (int i = 0; i <= n; ++i) E[i].clear(); for (int i = 1; i <= n; ++i){ scanf("%d", wht + i); v[i] = make(wht[i]); } int ui, vi; for (int i = 0; i < n - 1; i++){ scanf("%d%d", &ui, &vi); E[ui].push_back(vi); E[vi].push_back(ui); } bfs(); scanf("%d", &nQ); int xi, yi, vv; Node *nx, *ny; while (nQ--){ scanf("%d%d%d", &xi, &yi, &vv); nx = v[xi]; ny = v[yi]; int ans = deltaPath(nx, ny); if (ans < 0) ans = -ans; else ans = 0; assert(ans >= 0); printf("%d\n", ans); addPath(nx, ny, vv); } } return 0; }