社区讨论

link-cut-tree 被卡了,求放宽时限吧

P3379【模板】最近公共祖先(LCA)参与者 5已保存回复 8

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
8 条
当前快照
1 份
快照标识符
@lobpaf2j
此快照首次捕获于
2023/10/30 00:43
2 年前
此快照最后确认于
2023/11/04 05:23
2 年前
查看原帖
也不知道是哪里有问题。。。反正我的lct慢得很。。。
CPP
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <vector>

using namespace std;

#define LOCAL 0
#define MAXN 500000
#define MAXM 500000

struct TreeNode {
  bool rev;
  uint32_t pa;
  uint32_t lc;
  uint32_t rc;
};

TreeNode tree[MAXN+1];
uint32_t ancestors[MAXN+1];

inline bool IsRoot(uint32_t p)
{
  return (tree[tree[p].pa].lc != p) && (tree[tree[p].pa].rc != p);
}

void PushDownRev(uint32_t p)
{
  if (tree[p].lc != 0) {
    tree[tree[p].lc].rev = !tree[tree[p].lc].rev;
  }
  if (tree[p].rc != 0) {
    tree[tree[p].rc].rev = !tree[tree[p].rc].rev;
  }
  swap(tree[p].lc, tree[p].rc);
  tree[p].rev = false;
}

void PushAllRev(uint32_t p)
{
  int top = 0;
  ++top;
  ancestors[top] = p;
  while (!IsRoot(p)) {
    p = tree[p].pa;
    ++top;
    ancestors[top] = p;
  }
  while (top != 0) {
    p = ancestors[top];
    --top;
    if (tree[p].rev) {
      PushDownRev(p);
    }
  }
}

void LeftRotate(uint32_t p)
{
  uint32_t q;
  q = tree[p].rc;
  tree[p].rc = tree[q].lc;
  if (tree[q].lc != 0) {
    tree[tree[q].lc].pa = p;
  }
  tree[q].pa = tree[p].pa;
  if (!IsRoot(p)) {
    if (tree[tree[p].pa].lc == p) {
      tree[tree[p].pa].lc = q;
    } else {
      tree[tree[p].pa].rc = q;
    }
  }
  tree[q].lc = p;
  tree[p].pa = q;
}

void RightRotate(uint32_t p)
{
  uint32_t q;
  q = tree[p].lc;
  tree[p].lc = tree[q].rc;
  if (tree[q].rc != 0) {
    tree[tree[q].rc].pa = p;
  }
  tree[q].pa = tree[p].pa;
  if (!IsRoot(p)) {
    if (tree[tree[p].pa].lc == p) {
      tree[tree[p].pa].lc = q;
    } else {
      tree[tree[p].pa].rc = q;
    }
  }
  tree[q].rc = p;
  tree[p].pa = q;
}

void LctSplay(uint32_t p)
{
  uint32_t f, g;
  PushAllRev(p);
  while (!IsRoot(p)) {
    f = tree[p].pa;
    g = tree[f].pa;
    if (IsRoot(f)) {
      if (p == tree[f].lc) {
        RightRotate(f);
      } else {
        LeftRotate(f);
      }
    } else if (p == tree[f].lc && f == tree[g].lc) {
      RightRotate(g);
      RightRotate(f);
    } else if (p == tree[f].rc && f == tree[g].rc) {
      LeftRotate(g);
      LeftRotate(f);
    } else if (p == tree[f].lc && f == tree[g].rc) {
      RightRotate(f);
      LeftRotate(g);
    } else {
      LeftRotate(g);
      RightRotate(f);
    }
  }
}

uint32_t LctAccess(uint32_t p) 
{
  uint32_t last = 0;
  while (p != 0) {
    LctSplay(p);
    tree[p].rc = last;
    last = p;
    p = tree[p].pa;
  }
  return last;
}

void LctMakeRoot(uint32_t p)
{
  LctAccess(p);
  LctSplay(p);
  tree[p].rev = !tree[p].rev;
}

int ReadInteger(void)
{
  int x = 0, sign = 1;
  int ch;
  ch = getchar();
  while (ch<'0' || ch>'9') {
    if (ch == '-') {
      sign = -1;
    }
    ch = getchar();
  }
  while (ch>='0' && ch<='9') {
    x = x*10 + ch-'0';
    ch = getchar();
  }
  return x*sign;
}

int main(void)
{
#if LOCAL
  freopen("test.in", "r", stdin);
  freopen("test.out", "w", stdout);
#endif
  int n, m, root;
  int u, v, lca;
  n = ReadInteger();
  m = ReadInteger();
  root = ReadInteger();
  memset(tree, 0, (n+1)*sizeof(tree[0]));
  for (int i=0; i<n-1; ++i) {
    u = ReadInteger();
    v = ReadInteger();
    LctMakeRoot(u);
    tree[u].pa = v;
  }
  LctMakeRoot(root);
  for (int i=0; i<m; ++i) {
    u = ReadInteger();
    v = ReadInteger();
    LctAccess(u);
    lca = LctAccess(v);
    printf("%d\n", lca);
  }
  return 0;
}

回复

8 条回复,欢迎继续交流。

正在加载回复...