E. Wooden Game

onlyblues發表於2024-07-20

E. Wooden Game

You are given a forest of $k$ rooted trees$^{\text{∗}}$. Lumberjack Timofey wants to cut down the entire forest by applying the following operation:

  • Select a subtree$^{\text{†}}$ of any vertex of one of the trees and remove it from the tree.

Timofey loves bitwise operations, so he wants the bitwise OR of the sizes of the subtrees he removed to be maximum. Help him and find the maximum result he can obtain.

$^{\text{∗}}$ A tree is a connected graph without cycles, loops, or multiple edges. In a rooted tree, a selected vertex is called a root. A forest is a collection of one or more trees.

$^{\text{†}}$ The subtree of a vertex $v$ is the set of vertices for which $v$ lies on the shortest path from this vertex to the root, including $v$ itself.

Input

Each test consists of multiple test cases. The first line contains an integer $t$ ($1 \leq t \leq 10^4$) — the number of test cases. Then follows the description of the test cases.

The first line of each test case contains a single integer $k$ ($1 \leq k \leq 10^6$) — the number of trees in the forest.

This is followed by a description of each of the $k$ trees:

The first line contains a single integer $n$ ($1 \leq n \leq 10^6$) — the size of the tree. The vertices of the tree are numbered with integers from $1$ to $n$. The root of the tree is vertex number $1$.

The second line contains $n - 1$ integers $p_2, p_3, \ldots p_n$ ($1 \leq p_i < i$), where $p_i$ — the parent of vertex $i$.

It is guaranteed that the sum of $k$ and $n$ for all sets of input data does not exceed $10^6$.

Output

For each test case, output a single integer — the maximum result that can be obtained.

Example

input

3
1
1

2
4
1 2 2
6
1 1 3 1 3
1
10
1 2 2 1 1 5 7 6 4

output

1
7
10

Note

In the second test case, the trees look like this:

E. Wooden Game

The first operation removes the entire second tree.

E. Wooden Game

The second operation removes vertex $4$ from the first tree.

E. Wooden Game

The third operation removes the first tree. The result is $6|1|3 = 7$ ($|$ denotes bitwise OR).

In the third test case, the entire tree needs to be removed.

解題思路

  假設只有一棵樹,那麼 OR 的最大值就是這棵樹本身的大小 $n$。假設把一棵樹拆分成了 $m$ 個部分,每個部分的大小為 $a_i$,有 $a_1 \mid a_2 \mid \cdots \mid a_m \leq a_1 + a_2 + \cdots + a_n = n$,這是因為 OR 運算沒有進位。另外,對於一棵大小為 $n$ 的樹,我們可以拆分得到大小在 $1 \sim n$ 的任意一棵樹,每次只需刪除葉子即可。因此如果我們想讓某棵樹貢獻某個值時,只需透過刪除葉子來得到該大小的樹即可,而無需考慮如何拆分。

  因此現在的問題變成了,有 $k$ 個數,每個數可取的範圍是 $[1, n_i]$,求這 $k$ 個數 OR 的最大值。

  從高位往低位貪心考慮,對於某個位 $i$,如果至少有兩個數的第 $i$ 位是 $1$,則將其中一個數變小,使其第 $0$ 到第 $i-1$ 位變成 $1$,這樣透過 OR 就可以對答案貢獻 $2^{i+1} - 1$。如果只有一個數的第 $i$ 位是 $1$,則保留這一位,對答案貢獻 $2^i$。

  AC 程式碼如下,時間複雜度為 $O(n \log{n})$:

#include <bits/stdc++.h>
using namespace std;

typedef long long LL;

const int N = 1e6 + 5;

int a[N];

void solve() {
    int n;
    scanf("%d", &n);
    for (int i = 0; i < n; i++) {
        scanf("%d", a + i);
        for (int j = 0; j < a[i] - 1; j++) {
            scanf("%*d");
        }
    }
    sort(a, a + n, greater<int>());
    int ret = 0;
    for (int i = 0; i < n; i++) {
        for (int j = 19; j >= 0; j--) {
            if (a[i] >> j & 1) {
                if (ret >> j & 1) ret |= (1 << j) - 1;
                else ret |= 1 << j;
            }
        }
    }
    printf("%d\n", ret);
}

int main() {
    int t;
    scanf("%d", &t);
    while (t--) {
        solve();
    }
    
    return 0;
}

參考資料

  Codeforces Round 959 sponsored by NEAR (Div. 1 + Div. 2) A~E:https://zhuanlan.zhihu.com/p/709662276