#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; 
}