Codeforces и Polygon могут быть недоступны в период с 6 декабря, 22:00 (МСК) по 7 декабря, 00:00 (МСК) в связи с проведением технических работ. ×

Maintain subtree information using link/cut trees

Правка en1, от ouuan, 2019-06-12 18:40:35

In the tutorial of 1172E - Nauuo and ODT, I didn't write things on how to maintain subtree information, because I thought it was a popular trick. However, through tmwilliamlin168's comment, I realized that this trick may be not so common in other countries, so I decided to write a blog on it.

This blog will tell you how to maintain subtree information using LCT, with solutions on some problems, so you should know LCT before reading this blog.

Main Idea

The main idea is simple: record the sum of information of "virtual subtrees", where the "virtual subtrees" refers to the subtrees except the one in the Splay.

In the picture, $$$1$$$, $$$2$$$, $$$6$$$, $$$10$$$ are in a Splay, while $$$8$$$ and $$$12$$$ are in another. The "virtual subtrees" of $$$1$$$ is $$$3$$$ and $$$4$$$, the "virtual subtrees" of $$$4$$$ is $$$7$$$ and $$$8$$$, the node $$$8$$$ has no "virtual subtree".

You need to update the information when the "virtual subtrees" changes, usually, when accessing and linking.

An easy example is using LCT to maintain the size of subtrees.

Here are some codes:

struct Node
{
    int fa, ch[2], siz, vir; // father, two children, size of subtrees (including the root), size of virtual subtrees
} t[N];

void access(int x)
{
    for (int y = 0; x; x = t[y = x].fa)
    {
        Splay(x);
        t[x].vir -= t[y].siz; // update the size of virtual subtrees
        t[x].vir += t[t[x].ch[1]].siz;
        t[x].ch[1] = y;
        pushup(x); // update the information of the node x
    }
}

void link(int x, int y)
{
    makeroot(x);
    t[x].fa = y;
    t[y].vir += t[x].siz;
}

void pushup(int x)
{
    t[x].siz = t[t[x].ch[0]].siz + t[t[x].ch[1]].siz + t[x].vir + 1;
}

Problems

Some problems are in Chinese, I will translate the statements (in a simplified version).

[BJOI2014] Great Integration

There are initially $$$n$$$ nodes, there will be $$$q$$$ operations in two types:

  1. A x y add an edge between $$$x$$$ and $$$y$$$
  2. Q x y a query, asking how many simple paths are there which go through the edge between $$$x$$$ and $$$y$$$.

It is guaranteed that the graph is always a forest (one or more trees).

Input

n m
m lines of operations
Tutorial
Solution

UOJ #207. Gongjia toured Changsha

There is a tree consisting of $$$n$$$ nodes and a multiset of simple paths $$$S$$$. $$$S$$$ is initially empty. There are $$$m$$$ operations in $$$4$$$ types:

  1. x y u v $$$cut(x, y)$$$, $$$link(u, v)$$$
  2. x y insert the simple path $$$(x, y)$$$ in $$$S$$$
  3. x delete the $$$x$$$-th simple path inserted in $$$S$$$
  4. x y a query, asking if all simple paths in $$$S$$$ go through the edge $$$(x,y)$$$

It is guaranteed that the graph is always a tree.

Input

the id of subtask
n m
n-1 lines of the initial tree
m lines of operations
Tutorial
Solution

1172E - Nauuo and ODT

You can see the problem on Codeforces, and the tutorial is also available here.

История

 
 
 
 
Правки
 
 
  Rev. Язык Кто Когда Δ Комментарий
en2 Английский ouuan 2020-06-23 02:39:24 31 Tiny change: '(x);\n t[' -> '(x);\n access(y);\n Splay(y);\n t['
en1 Английский ouuan 2019-06-12 18:40:35 10514 Initial revision (published)