当前位置:首页 > 提高组 > 【CSP-S 2019】括号树(洛谷P5658)解题报告:栈+DFS+异或优化详解

【CSP-S 2019】括号树(洛谷P5658)解题报告:栈+DFS+异或优化详解

2个月前 (06-13)

【CSP-S 2019】括号树(洛谷P5658)解题报告:栈+DFS+异或优化详解  括号树问题 深度优先搜索 栈数据结构 异或运算 第1张

一、题目解读

括号树问题洛谷P5658)要求处理一个由括号序列转化的树结构:每个节点表示一个括号,'('为子节点,')'为父节点。题目给定一棵n个节点的,需计算每个节点的深度(括号层数),并输出所有节点深度与节点编号乘积的异或和。核心在于将括号序列转化为树,并高效计算深度信息。

二、解题思路

采用“+深度优先搜索DFS)”的策略:

1. 栈处理括号匹配:用栈维护未匹配的左括号,遇到')'时弹出栈顶,建立父子关系。

2. 树构建与深度计算:通过父节点输入建立树结构,DFS遍历时利用栈弹出更新深度(dp值)。

3. 累积深度和:sum数组记录子树深度总和,避免重复计算。

4. 异或求解:最终遍历所有节点,异或乘积i*sum[i]得到答案。

三、解题步骤

1. 输入处理:读入n、括号序列s及父节点数组fa,构建树边tree。

2. DFS遍历:从根节点1开始,递归处理子节点:

    遇到'('入栈,')'时弹出并更新dp(深度继承父节点+1)。

    累加sum:sum[u] = sum[父节点] + dp[u]。

3. 异或计算:遍历节点i,异或值i*sum[i]累加至ans。

四、代码与注释

#include <iostream>
#include <vector>
#include <stack>
using namespace std;

const int MAXN = 5e5 + 10; // 节点数上限
vector<int> tree[MAXN]; // 邻接表存树
char s[MAXN]; // 括号序列
int fa[MAXN]; // 父节点数组
long long dp[MAXN], sum[MAXN]; // 深度、子树深度和
stack<int> stk; // 存储未匹配左括号

void dfs(int u) { // 递归遍历节点u
    int last = 0; // 记录匹配的右括号
    if (s[u] == '(') { // 左括号入栈
        stk.push(u);
    } else if (!stk.empty()) { // 匹配右括号
        last = stk.top(); // 获取栈顶(父节点)
        stk.pop(); // 弹出
        dp[u] = dp[fa[last]] + 1; // 继承深度+1
    }
    
    sum[u] = sum[fa[u]] + dp[u]; // 累加子树深度和
    
    for (int v : tree[u]) { // 遍历子节点
        dfs(v);
    }
    
    if (s[u] == '(') { // 左括号处理(特判栈顶是否自匹配)
        if (!stk.empty() && stk.top() == u) {
            stk.pop();
        }
    } else if (last!= 0) { // 右括号入栈(父节点)
        stk.push(last);
    }
}

int main() {
    ios::sync_with_stdio(false); // 关闭同步加速输入
    cin.tie(nullptr);
    
    int n;
    cin >> n; // 读入节点数
    cin >> (s + 1); // 读入括号序列(从s[1]开始)
    
    for (int i = 2; i <= n; ++i) { // 建立树边(从2开始)
        cin >> fa[i];
        tree[fa[i]].push_back(i);
    }
    
    dfs(1); // 从根节点开始DFS
    
    long long ans = 0;
    for (int i = 1; i <= n; ++i) {
        ans ^= (i * sum[i]); // 异或乘积
    }
    
    cout << ans << endl;
    return 0;
}

五、总结

1. 核心思想:通过栈维护括号匹配关系,将序列转化为树结构,利用DFS高效计算深度信息。

2. 优化点:

累积sum数组避免重复深度求和。

异或运算简化最终答案计算。

3. 复杂度:O(n),单次DFS遍历树。

4. 应用拓展:此类问题常结合栈处理括号序列与树结构,需灵活转化模型。


原创内容 转载请注明出处

分享给朋友:

相关文章

力扣225题:用队列实现栈 - 双队列解法详解

力扣225题:用队列实现栈 - 双队列解法详解

内容简介本文详细解析了力扣225题"用队列实现栈"的双队列解法。通过两个队列的巧妙配合,实现了栈的后进先出(LIFO)特性。文章包含完整注释代码、算法思路讲解和复杂度分析,帮助读者...

牛客13279题解:利用递归与深度优先搜索计算树的最大高度(附完整代码)

牛客13279题解:利用递归与深度优先搜索计算树的最大高度(附完整代码)

一、题目解读牛客13279题要求计算给定树的最大高度。题目输入一棵以邻接表形式表示的树(节点从0开始编号),需要输出从根节点到最深叶节点的最长路径长度。树的结构由n个节点和n-1条边构成,保证为连通无...

力扣LCP41题解析:棋盘翻转算法优化与C++深度优先搜索策略

力扣LCP41题解析:棋盘翻转算法优化与C++深度优先搜索策略

一、题目解读力扣LCP41题要求玩家在给定棋盘中,通过翻转单个棋子(将'.'变为'X'),使其周围'X'连锁翻转'O',最终计算最多能翻...

洛谷P1141题解:迷宫连通块问题的深度优先搜索算法与代码解析

洛谷P1141题解:迷宫连通块问题的深度优先搜索算法与代码解析

一、题目解读洛谷P1141题目要求处理一个由字符构成的迷宫,其中相同字符形成连通块,不同字符构成分隔。题目需统计连通块数量及大小,并支持查询两点是否属于同一连通块。核心在于高效识别并标记迷宫中的连通区...

2023年GESP五级烹饪问题解题指南:位运算优化AND最大值求解

2023年GESP五级烹饪问题解题指南:位运算优化AND最大值求解

一、题目解读2023年GESP五级编程竞赛中的“烹饪问题”(对应洛谷B3930)要求从给定的整数数组中寻找一个元素,使其与数组中其他任意元素的按位与(AND)结果最大。题目需在保证结果尽可能大的同时,...

洛谷P2420题解析:树结构异或路径的高效求解算法

洛谷P2420题解析:树结构异或路径的高效求解算法

一、题目解读洛谷P2420题要求处理一棵树上的路径异或问题。给定一棵包含N个节点的树,每条边有权值,需回答M次查询:求节点u到节点v路径上所有边权值的异或和。题目关键在于如何高效利用树结构和异或运算的...

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。