#P10155. [2017备战wc]树
[2017备战wc]树
#include <stdio.h>
#include <memory.h>
#include <stdlib.h>
#include <assert.h>
#include <time.h>
#include <ctype.h>
#include <math.h>
#include <stdbool.h>
/* #define DEBUG */
typedef int (*cmp_t) (const void *, const void *);
typedef unsigned uint;
typedef long long int64;
typedef unsigned long long uint64;
#define max(i, j) ({int _ = (i), __ = (j); _ > __ ? _ : __;})
#define min(i, j) ({int _ = (i), __ = (j); _ < __ ? _ : __;})
#define swap(T, i, j) ({T _ = (i); (i) = (j); (j) = _;})
#define oo 0x3F3F3F3F
#ifdef DEBUG
#define cerr(...) fprintf (stderr, __VA_ARGS__)
#define cvar(x) cerr ("[" #x ": %d]\n", x)
void disp (char *s, int *x, int n) {int i; cerr ("[%s: ", s); for (i = 0; i < n - 1; ++i) cerr ("%d ", x[i]); if (n) cerr ("%d", x[i]); cerr ("]\n");}
#else
#define cerr(...) ({})
#define cvar(...) ({})
#define disp(...) ({})
#endif
#define CR cerr ("\n")
#ifdef WIN32
#define fmt64 "%I64d"
#else
#define fmt64 "%lld"
#endif
#define maxn 110000
#define maxv 220000
#define hpos(v) ((v) - lct + heap)
#define setc(p,d,q) (((p)->c[d] = (q))->f = (p))
#define sethc(p,d,q) (((p)->d = (q))->f = (p))
typedef struct info {int key, ref, fer;} info;
typedef struct elem {struct elem *lc, *rs, *f; int key; } elem;
typedef struct node
{
struct node *c[2], *f;
bool rev; elem *hrt;
int vmk, smk, mrk;
info self, sbtr; /* =self= is the unsual LCT, it contains the original data */
} node;
node lct[maxv], *null = lct, *root = lct + 1;
elem heap[maxv], *pair[maxv];
int globe, fth[maxn], n, m;
elem *meld (elem *p, elem *q)
{
/* cerr ("meld: %d %d\n", p - heap, q - heap); */
if (p == heap) return q; if (q == heap) return p;
if (p->key > q->key) swap (elem *, p, q);
return sethc (q, rs, p->lc), sethc (p, lc, q), p->rs = p->f = heap, p;
}
elem *combine (elem *t)
{
elem *p, *q; int w = 0;
for (; t != heap && t->rs != heap; p = t, q = t->rs, t = q->rs, pair[++w] = meld (p, q));
for (t->f = heap; w; t = meld (t, pair[w--]));
return assert (t->f == heap), t;
}
elem *hdel (elem *R, elem *p)
{
if (p == heap) return assert (R->f == heap || R == heap), R;
elem *t = combine (p->lc); assert (t->f == heap || t == heap);
if (p == R) return assert (p->f == heap && p->rs == heap), p->lc = heap, t;
assert (p->f != heap);
if (p->f->lc == p)
sethc (p->f, lc, p->rs);
else
assert (p->f->rs == p), sethc (p->f, rs, p->rs);
return p->f = p->lc = p->rs = heap, meld (t, R);
}
bool isr (node *t) {return t->f == null || (t->f->c[0] != t && t->f->c[1] != t);}
void put_rev (node *t)
{
if (t == null) return ;
swap (node *, t->c[0], t->c[1]);
swap (int, t->self.ref, t->self.fer);
swap (int, t->sbtr.ref, t->sbtr.fer);
t->smk = -t->smk;
t->vmk = -t->vmk;
t->rev ^= 1;
}
/* it only affect the `self' part, so just update `self' */
void put_add (node *t, int v)
{
if (t == null) return ;
t->mrk += v;
t->self.key += v;
t->self.ref += v;
t->self.fer += v;
}
/* ..and also only self */
void push_down (node *x)
{
if (x->rev) put_rev (x->c[0]), put_rev (x->c[1]), x->rev = 0;
if (x->mrk) put_add (x->c[0], x->mrk), put_add (x->c[1], x->mrk), x->mrk = 0;
}
/* but here, you must update both */
node *update (node *T)
{
node *L = T->c[0], *R = T->c[1];
/* for simplicity */
inline void mul (info *t, info *l, info *r)
{
t->ref = min (l->ref, min (t->key, r->ref + T->vmk) + L->smk);
t->fer = min (r->fer, min (t->key, l->fer - T->vmk) - R->smk);
}
T->smk = L->smk + T->vmk + R->smk;
mul (&T->self, &L->self, &R->self);
mul (&T->sbtr, &L->sbtr, &R->sbtr);
return T;
}
void rotate (node *x)
{
node *y = x->f, *z = y->f; int d = x == y->c[1]; assert (x != null && y != null);
push_down (y), push_down (x);
x->f = z; if (!isr (y)) z->c[y == z->c[1]] = x;
setc (y, d, x->c[!d]);
setc (x, !d, update (y));
}
node *splay (node *t)
{
if (t == null) return t; assert (null->c[0] == null && null->c[1] == null);
for (push_down (t); !isr (t); rotate (t))
if (!isr (t->f))
rotate ((t->f->f->c[1] == t->f) == (t->f->c[1] == t) ? t->f : t);
return update (t);
}
node *find_head (node *t)
{
for (; push_down (t), t->c[0] != null; t = t->c[0]);
return t;
}
void dfs_show (elem *t)
{
void dfs (elem *t)
{
if (t == heap) return ;
cerr ("%d ", t - heap);
dfs (t->lc), dfs (t->rs);
}
dfs (t), CR;
}
void relink (node *p, node *q) /* set p's prefered child to q */
{
/* if (p == lct + 2) dfs_show (p->hrt); */
node *t = find_head (p->c[1]); q = find_head (q), splay (q);
elem *ht = t - lct + heap, *hq = q - lct + heap;
ht->key = min (p->c[1]->self.ref, p->c[1]->sbtr.ref);
hq->key = oo;
cerr ("[relink %d: +%d(%d) -%d]\n", p - lct, t - lct, ht->key, q - lct);
p->hrt = hdel (p->hrt, hq);
p->hrt = meld (p->hrt, ht);
p->sbtr.key = p->hrt->key;
/* if (p == lct + 2) dfs_show (p->hrt); */
p->c[1] = q;
}
node *expose (node *p)
{
node *q = null;
for (; p != null; p = p->f)
relink (splay (p), q), update (q = p);
return q;
}
/* must be careful */
void evert (node *p)
{
p = expose (p), globe += p->smk, put_rev (p);
}
node *find_prev (node *t)
{
node *bak = t; for (splay (t), t = t->c[0]; push_down (t), t->c[1] != null; t = t->c[1]);
return cerr ("%d's prev is : %d\n", bak - lct, t - lct), splay (t);
}
void modify_vertex (node *t, int x) {expose (t), splay (t), t->self.key += x, update (t);}
void modify_path (node *p, node *q, int x) {evert (q), put_add (expose (p), x), evert (root);}
int query_vertex (node *t) {return expose (t), splay (t), t->self.key + t->smk + globe;}
int query_subtree (node *p) {return expose (p), splay (p), min (p->self.key, p->sbtr.key) + globe + p->smk;}
int query_path (node *p, node *q)
{
evert (p), expose (q), splay (q);
int ret = q->self.ref + globe;
return evert (root), ret;
}
void modify_subtree (node *p, int x)
{
if (p == root) return (void)(globe += x);
expose (p), p = find_prev (p), p->vmk += x, update (p);
}
void link_cut (node *p, node *f) /* change p's father to f */
{
node *q; assert (p != root);
expose (p), p = find_prev (p), q = find_prev (p);
expose (q), splay (q), splay (p); /* be careful with the order */
cvar (q - lct);
p->vmk += q->smk; /* delete p from q */
q->hrt = hdel (q->hrt, p - lct + heap); /* maintain q->hrt */
q->sbtr.key = q->hrt->key;
update (q);
expose (f), splay (f); /* add p to f */
p->vmk -= f->smk, update (p);
(p - lct + heap)->key = min (p->self.ref, p->sbtr.ref);
f->hrt = meld (f->hrt, p - lct + heap);
f->sbtr.key = f->hrt->key;
update (f);
p->f = f;
}
void contruct (node *v, node *f, node *u) /* v -> u -> f */
{
*u = *null, v->c[0] = v->c[1] = u->c[0] = u->c[1] = null, v->f = u, u->f = f;
v->sbtr.key = v->hrt->key, update (v);
if (u == null) return ;
hpos (v)->key = min (v->sbtr.key, v->self.key);
u->hrt = meld (u->hrt, hpos (v));
u->sbtr.key = u->hrt->key, update (u);
u->self.key = oo;
hpos (u)->key = u->sbtr.key;
f->hrt = meld (f->hrt, hpos (u));
}
void init ()
{
int i;
*heap = (elem){heap, heap, heap, oo};
*null = (node){{null, null}, null, 0, heap, 0, 0, 0, {oo, oo, oo}, {oo, oo, oo}};
scanf ("%d%d", &n, &m);
for (i = 1; i <= n; ++i)
scanf ("%d%d", &fth[i], &lct[i].self.key);
for (i = 1; i < n * 2; ++i)
heap[i] = *heap, lct[i].hrt = heap;
for (i = n; i; --i)
contruct (lct + i, lct + fth[i], lct + (fth[i] ? n + i - 1 : 0));
/* for (i = 1; i < n * 2; ++i) */
/* cvar (lct[i].f - lct); */
/* for (i = 1; i < 2 * n; ++i) */
/* /\* cvar (null->c[0] - null), *\/expose (lct + i); */
}
int main ()
{
int i, s, j; char cmd[5];
init ();
for (; m--; )
if (scanf ("%s", cmd), cmd[0] == 'E')
scanf ("%d", &s), evert (lct + s), root = lct + s;
else if (cmd[0] == 'L' && cmd[1] == 'C')
scanf ("%d%d", &i, &s), link_cut (lct + i, lct + s);
else if (cmd[0] == 'C' && cmd[1] == 'V')
scanf ("%d%d", &i, &s), modify_vertex (lct + i, s);
else if (cmd[0] == 'C' && cmd[1] == 'P')
scanf ("%d%d%d", &i, &j, &s), modify_path (lct + i, lct + j, s);
else if (cmd[0] == 'C' && cmd[1] == 'S')
scanf ("%d%d", &i, &s), modify_subtree (lct + i, s);
else if (cmd[0] == 'Q' && cmd[1] == 'V')
scanf ("%d", &i), printf ("%d\n", query_vertex (lct + i));
else if (cmd[0] == 'Q' && cmd[1] == 'P')
scanf ("%d%d", &i, &j), printf ("%d\n", query_path (lct + i, lct + j));
else if (cmd[0] == 'Q' && cmd[1] == 'S')
scanf ("%d", &i), printf ("%d\n", query_subtree (lct + i));
return 0;
}