P3920 [WC2014]紫荆花之恋 [点分树,替罪羊树]

Posted isaunoya

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P3920 [WC2014]紫荆花之恋 [点分树,替罪羊树]相关的知识,希望对你有一定的参考价值。

点分树搞出来,然后搞个快点的平衡树。
点分树膨胀的时候就搞重构,没了。。。说的这么轻巧倒是写了3h 23333

// powered by c++11
// by Isaunoya
#include <bits/stdc++.h>
#define rep(i, x, y) for (register int i = (x); i <= (y); ++i)
#define Rep(i, x, y) for (register int i = (x); i >= (y); --i)
#define pb emplace_back
using namespace std;
using ll = long long;
const int io_size = 1 << 23 | 233;
const int io_limit = 1 << 22;
struct io_in {
  char ch;
#ifndef __WIN64
  char getchar() {
    static char buf[io_size], *p1 = buf, *p2 = buf;

    return (p1 == p2) && (p2 = (p1 = buf) + fread(buf, 1, io_size, stdin), p1 == p2) ? EOF : *p1++;
  }
#endif
  template <class T>

  void read(T& x) {
    bool f = 0;
    while ((ch = getchar()) < 48 && ~ch) f ^= (ch == 45);

    x = ~ch ? (ch ^ 48) : 0;
    while ((ch = getchar()) > 47) x = x * 10 + (ch ^ 48);
    x = f ? -x : x;
  }

  io_in& operator>>(int& x) { return read(x), *this; }

  io_in& operator>>(ll& x) { return read(x), *this; }
} in;

struct io_out {
  char buf[io_size], *s = buf;
  int st[233];

  ~io_out() { flush(); }

  void io_chk() {
    if (s - buf > io_limit) flush();
  }

  void flush() { fwrite(buf, 1, s - buf, stdout), fflush(stdout), s = buf; }

  io_out& operator<<(char c) { return *s++ = c, *this; }

  template <class T>

  void write(T x) {
    if (x < 0) *s++ = ‘-‘, x = -x;
    do {
      st[++st[0]] = x % 10, x /= 10;
    } while (x);
    while (st[0]) *s++ = st[st[0]--] ^ 48;
  }
  io_out& operator<<(int x) { return write(x), io_chk(), *this; }
  io_out& operator<<(ll x) { return write(x), io_chk(), *this; }
} out;
void cmax(int& x, const int& y) {
  if (x < y) x = y;
}
int n;
const int maxn = 1e5 + 51;
const double alpha = 0.8;
const int mod = 1e9;
vector<int> g[maxn];
int fa[maxn], val[maxn];

struct Edge {
  int v, nxt;
} e[maxn << 1];
int head[maxn], cnt = 0;

void add_edge(int u, int v) {
  e[++cnt] = { v, head[u] }, head[u] = cnt;
  e[++cnt] = { u, head[v] }, head[v] = cnt;
}

int f[maxn][19], dep[maxn], len[maxn];
int lca(int x, int y) {
  if (dep[x] < dep[y]) x ^= y ^= x ^= y;
  for (int i = 17; ~i; i--)
    if (dep[f[x][i]] >= dep[y]) x = f[x][i];
  if (x == y) return x;
  for (int i = 17; ~i; i--)
    if (f[x][i] ^ f[y][i]) x = f[x][i], y = f[y][i];
  return f[x][0];
}

int dis(int x, int y) { return len[x] + len[y] - 2 * len[lca(x, y)]; }

struct ScapeGoatTree {
  struct Goat {
    int val, sz;
    Goat* ch[2];
    Goat() {}
    bool bad() { return ch[0]->sz >= sz * alpha + 5 || ch[1]->sz >= sz * alpha + 5; }
  } * tr1[maxn], *tr2[maxn], *pool[maxn << 8], *null, *sta[maxn], mem[maxn << 8];

  int tot, top;

  void init() {
    null = new Goat(), null->ch[0] = null->ch[1] = null, null->sz = null->val = 0;
    for (int i = 0; i < (maxn << 8); i++) pool[i] = mem + i;
    tot = (maxn << 8) - 1;
    for (int i = 0; i < maxn; i++) tr1[i] = tr2[i] = null;
  }

  Goat** insert(Goat*& p, int val) {
    if (p == null) {
      p = pool[tot--], p->ch[0] = p->ch[1] = null;
      p->val = val, p->sz = 1;
      return &null;
    }
    p->sz++;
    Goat** o = insert(p->ch[p->val < val], val);
    if (p->bad()) o = &p;
    return o;
  }

  int getrk(Goat* p, int val) {
    if (p == null) return 0;
    return (p->val >= val) ? getrk(p->ch[0], val) : (getrk(p->ch[1], val) + p->ch[0]->sz + 1);
  }

  void clr(Goat* p) {
    if (p == null) return;
    if (p->ch[0] != null) clr(p->ch[0]);
    pool[++tot] = p;
    if (p->ch[1] != null) clr(p->ch[1]);
  }

  void travel(Goat* p) {
    if (p == null) return;
    if (p->ch[0] != null) travel(p->ch[0]);
    sta[++top] = p;
    if (p->ch[1] != null) travel(p->ch[1]);
  }

  Goat* build(int l, int r) {
    if (l > r) return null;
    int mid = l + r >> 1;
    Goat* p = sta[mid];
    p->sz = r - l + 1;
    p->ch[0] = build(l, mid - 1);
    p->ch[1] = build(mid + 1, r);
    return p;
  }

  void rebuild(Goat*& p) { top = 0, travel(p), p = build(1, top); }

  void Insert(Goat*& p, int val) {
    Goat** o = insert(p, val);
    if (*o != null) rebuild(*o);
  }
} sgt;

int sz[maxn], mx[maxn], vis[maxn], siz, rt;

void findrt(int u, int fa) {
  sz[u] = 1, mx[u] = 0;
  for (int i = head[u]; i; i = e[i].nxt) {
    int v = e[i].v;
    if (v ^ fa && !vis[v]) {
      findrt(v, u), sz[u] += sz[v], cmax(mx[u], sz[v]);
    }
  }
  cmax(mx[u], siz - sz[u]);
  if (mx[u] < mx[rt]) rt = u;
}

void dfs(int u, int f, int rt) {
  sgt.Insert(sgt.tr1[rt], dis(u, rt) - val[u]);
  if (fa[rt]) sgt.Insert(sgt.tr2[rt], dis(u, fa[rt]) - val[u]);
  for (int i = head[u]; i; i = e[i].nxt) {
    int v = e[i].v;
    if (v ^ f && !vis[v]) dfs(v, u, rt);
  }
}

void solve(int u, int f) {
  int totsz = siz;
  fa[u] = f, vis[u] = 1, dfs(u, 0, u);
  for (int i = head[u]; i; i = e[i].nxt) {
    int v = e[i].v;
    if (!vis[v]) {
      rt = 0, siz = sz[v] > sz[u] ? totsz - sz[u] : sz[v];
      findrt(v, 0), g[u].pb(rt), solve(rt, u);
    }
  }
}

void recover(int x) {
  ++siz, vis[x] = 0, sgt.clr(sgt.tr1[x]), sgt.clr(sgt.tr2[x]);
  sgt.tr1[x] = sgt.tr2[x] = sgt.null;
  for (int v : g[x]) recover(v);
  g[x].clear();
}

void rebuild(int x) {
  siz = 0, recover(x), rt = 0, findrt(x, 0);
  if (fa[x])
    for (int i = 0, lim = g[fa[x]].size(); i < lim; i++)
      if (g[fa[x]][i] == x) g[fa[x]][i] = rt;
  solve(rt, fa[x]);
}

ll ans = 0;
int insert(int x) {
  for (int i = x; fa[i]; i = fa[i]) {
    int ds = val[x] - dis(x, fa[i]) + 1;
    ans += sgt.getrk(sgt.tr1[fa[i]], ds) - sgt.getrk(sgt.tr2[i], ds);
  }
  sgt.Insert(sgt.tr1[x], -val[x]);
  for (int i = x; fa[i]; i = fa[i]) {
    int ds = dis(fa[i], x) - val[x];
    sgt.Insert(sgt.tr1[fa[i]], ds);
    sgt.Insert(sgt.tr2[i], ds);
  }
  int res = 0;
  for (int i = x; fa[i]; i = fa[i])
    if (sgt.tr1[i]->sz >= sgt.tr1[fa[i]]->sz * alpha + 5) res = fa[i];
  return res;
}

signed main() {
  // code begin.
  int FUCK;
  in >> FUCK >> n, mx[rt = 0] = 1e9, sgt.init();
  rep(i, 1, n) {
    int qwq;
    in >> fa[i] >> qwq >> val[i];
    f[i][0] = fa[i] ^ (ans % mod), fa[i] = f[i][0];
    dep[i] = dep[fa[i]] + 1, len[i] = len[fa[i]] + qwq, vis[i] = 1;
    if (fa[i]) g[fa[i]].pb(i), add_edge(f[i][0], i);
    for (int j = 1; (1 << j) + 1 <= dep[i]; j++) f[i][j] = f[f[i][j - 1]][j - 1];
    int x = insert(i);
    if (x) rebuild(x);
    out << ans << ‘
‘;
  }
  return 0;
  // code end.
}

以上是关于P3920 [WC2014]紫荆花之恋 [点分树,替罪羊树]的主要内容,如果未能解决你的问题,请参考以下文章

bzoj3435[Wc2014]紫荆花之恋 替罪点分树套SBT

[WC2014]紫荆花之恋

luogu P3920 [WC2014]紫荆花之恋

BZOJ 3435: [Wc2014]紫荆花之恋

[WC 2014]紫荆花之恋

Wc2014 紫荆花之恋