双向链表练习题(2019牛客国庆集训派对day1)(二叉树)

mac2022-06-30  100

双向链表练习题(2019牛客国庆集训派对day1)(二叉树)

时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32768K,其他语言65536K Special Judge, 64bit IO Format: %lld

judge:双向链表练习题

题目描述

Bobo 有 n 个列表 L 1 , L 2 , … , L n L_1, L_2, \dots, L_n L1,L2,,Ln. 初始时, L i L_i Li仅包含元素 i i i, 即 L i = [ i ] L_i = [i] Li=[i] 他依次执行了 m m m 次操作。第 i i i 次操作由两个整数 a i , b i a_i, b_i ai,bi 指定, 每次操作分为两步:

L a i ← r e v e r s e ( L a i + L b i ) L_{a_i} \leftarrow \mathrm{reverse}(L_{a_i} + L_{b_i}) Laireverse(Lai+Lbi), 其中 ← \leftarrow 表示赋值, + + + 表示列表的连接, r e v e r s e \mathrm{reverse} reverse 表示列表的反转。例如, r e v e r s e ( [ 1 , 2 ] + [ 3 , 4 , 5 ] ) = [ 5 , 4 , 3 , 2 , 1 ] \mathrm{reverse}([1, 2] + [3, 4, 5]) = [5, 4, 3, 2, 1] reverse([1,2]+[3,4,5])=[5,4,3,2,1]. L b i ← [ ] L_{b_i} \leftarrow [] Lbi[]. 其中 [ ] [] [] 表示空的列表。 输出 m 次操作后, L 1 L_1 L1 的元素。

输入描述:

输入文件包含多组数据,请处理到文件结束。 每组数据的第一行包含两个整数 n n n m m m. 接下来 m m m 行,其中第 i i i 行包含 2 2 2 个整数 a i , b i a_i, b_i ai,bi.

1 ≤ n , m ≤ 1 0 5 1 \leq n, m \leq 10^5 1n,m105

1 ≤ a i , b i ≤ n , a i ≠ b i 1 \leq a_i, b_i \leq n, a_i \neq b_i 1ai,bin,ai=bi

n n n 的总和, m m m 的总和都不超过 5 × 1 0 5 5 \times 10^5 5×105.

输出描述:

对于每组数据,先输出 L 1 L_1 L1 的长度 ∣ L 1 ∣ |L_1| L1 ,再输出 ∣ L 1 ∣ |L_1| L1 个整数,表示 L 1 L_1 L1 的元素。

示例1

输入

2 1 1 2 2 1 2 1 3 3 3 2 3 2 1 3

输出

2 2 1 0 3 2 3 1

题解

根据点与点的相对关系建立二叉树,最后从根节点遍历,通过判断奇偶来判断左右孩子的输出顺序。

例如输入

5 3 2 3 2 4 5 2

则数据变化应该为

c n t = 1 cnt=1 cnt=1 ( L [ 2 ] , L [ 3 ] ) (L[2],L[3]) (L[2],L[3]) l s o n [ 1 ] = N + 3 lson[1]=N+3 lson[1]=N+3 r s o n [ 1 ] = N + 2 rson[1]=N+2 rson[1]=N+2 L [ 2 ] = c n t = 1 L[2]=cnt=1 L[2]=cnt=1 L [ 3 ] = 0 L[3]=0 L[3]=0 c n t = 2 cnt=2 cnt=2 ( L [ 2 ] , L [ 4 ] ) (L[2],L[4]) (L[2],L[4]) l s o n [ 2 ] = N + 4 lson[2]=N+4 lson[2]=N+4 r s o n [ 2 ] = L [ 2 ] = 1 rson[2]=L[2]=1 rson[2]=L[2]=1 L [ 2 ] = c n t = 2 L[2]=cnt=2 L[2]=cnt=2 c n t = 3 cnt=3 cnt=3 ( L [ 5 ] , L [ 2 ] ) l s o n [ 3 ] = L [ 2 ] = 2 r s o n [ 3 ] = N + 5 L [ 5 ] = c n t = 3 L [ 2 ] = 0 (L[5],L[2])\\lson[3]=L[2]=2\\rson[3]=N+5\\L[5]=cnt=3\\L[2]=0 (L[5],L[2])lson[3]=L[2]=2rson[3]=N+5L[5]=cnt=3L[2]=0

图解应该是这样 1. 2. 3.

dfs的序应该为

u = L [ 2 ] u=L[2] u=L[2] f = 0 a [ 1 ] = N + 4 f=0\\a[1]=N+4 f=0a[1]=N+4 u = 1 u=1 u=1 f = 1 a [ 2 ] = N + 2 a [ 3 ] = N + 3 f=1\\a[2]=N+2\\a[3]=N+3 f=1a[2]=N+2a[3]=N+3

而如果搜索以 L [ 2 ] L[2] L[2] 为根节点的序列,那就从这里开始搜索: 并且通过判断奇偶可以判断左右孩子的输出顺序

答案应该是4 2 3

代码

#include <bits/stdc++.h> using namespace std; typedef long long ll; const int N = 1e5 + 5; int lson[N], rson[N]; int cnt = 0; int L[N]; int a[N], tot = 0; int n, m; void dfs(int u, int f) { if (u > N) { a[++tot] = u - N; return; } if (u == 0) return; if (f) { dfs(rson[u], f ^ 1); dfs(lson[u], f ^ 1); } else { dfs(lson[u], f ^ 1); dfs(rson[u], f ^ 1); } } int main() { // freopen("in","r",stdin); while (scanf("%d %d", &n, &m) == 2) { cnt = 0; for (int i = 1; i <= n; i++) L[i] = N + i; for (int i = 1; i <= m; i++) { int a, b; scanf("%d %d", &a, &b); cnt++; lson[cnt] = L[b]; rson[cnt] = L[a]; L[a] = cnt; L[b] = 0; } tot = 0; dfs(L[1], 0); printf("%d", tot); for (int i = 1; i <= tot; i++) { printf(" %d", a[i]); } puts(""); } return 0; }
最新回复(0)