2022 逻辑表达式 · 方案一 递归分治
每次在区间里找最外层运算符,短路就跳过右边
正文
// CSP-J 2022 复赛 T3 · 逻辑表达式
// 原题:https://oj.yecheng.tv/p/CSPJ2022C
// 题意:给一个含 0、1、&、|、() 的中缀表达式。规定 & 优先于 |,同级从左往右。
// 计算时要模拟「短路」:a&b 里 a 为 0 就不算 b;a|b 里 a 为 1 就不算 b。
// 输出表达式的值,以及 & 型短路、| 型短路各出现了多少次;
// 被外层短路掉的部分内部不再统计。
//
// 方案一 · 递归分治(好懂,但每次都要扫一遍区间,整体 O(n^2))
// dfs(l, r) 计算区间 [l, r) 的值:
// 先找最外层的第一个 |(优先级最低,且同级从左往右算,所以取最左边那个);
// 找不到再找最外层的第一个 &;
// 都没有,说明整段被一对括号包住,脱掉括号继续。
// 找到运算符后先算左边:
// 若是 | 且左边是 1 —— 短路,计数加一,右边整体跳过;
// 若是 & 且左边是 0 —— 短路,计数加一,右边整体跳过;
// 否则老老实实算右边。
// 「跳过右边」正好天然满足了「内部不再统计」这条规则。
#include <bits/stdc++.h>
using namespace std;
string s;
long long cntAnd = 0, cntOr = 0;
int dfs(int l, int r) {
int depth = 0, pos = -1;
for (int i = l; i < r; i++) { // 找最外层的第一个 |
if (s[i] == '(') depth++;
else if (s[i] == ')') depth--;
else if (depth == 0 && s[i] == '|') { pos = i; break; }
}
if (pos != -1) {
int L = dfs(l, pos);
if (L == 1) { // | 型短路:右边不用算了
cntOr++;
return 1;
}
int R = dfs(pos + 1, r);
return L | R;
}
for (int i = l; i < r; i++) { // 找最外层的第一个 &
if (s[i] == '(') depth++;
else if (s[i] == ')') depth--;
else if (depth == 0 && s[i] == '&') { pos = i; break; }
}
if (pos != -1) {
int L = dfs(l, pos);
if (L == 0) { // & 型短路:右边不用算了
cntAnd++;
return 0;
}
int R = dfs(pos + 1, r);
return L & R;
}
if (s[l] == '(' && s[r - 1] == ')') return dfs(l + 1, r - 1);
return s[l] - '0';
}
int main() {
freopen("expr.in", "r", stdin);
freopen("expr.out", "w", stdout);
cin >> s;
cout << dfs(0, (int)s.size()) << "\n";
cout << cntAnd << " " << cntOr << "\n";
return 0;
}
CSP-J 标程 · 复赛真题的其它内容
- 2019 数字游戏 · 方案一 逐字符统计
- 2019 数字游戏 · 方案二 二进制位运算
- 2020 优秀的拆分 · 方案一 贪心从大到小减
- 2020 优秀的拆分 · 方案二 直接看二进制位
- 2021 分糖果 · 方案一 枚举每个 k
- 2021 分糖果 · 方案二 看余数在哪一段
- 2022 乘方 · 方案一 边乘边判断
- 2022 乘方 · 方案二 快速幂加封顶
- 2023 小苹果 · 方案一 照规则真模拟
- 2023 小苹果 · 方案二 只盯住两个数字
- 2024 扑克牌 · 方案一 用集合去重
- 2024 扑克牌 · 方案二 二维布尔表
- 2025 拼数 · 方案一 收集后降序排序
- 2025 拼数 · 方案二 桶计数
- 2019 公交换乘 · 方案一 暴力匹配
- 2019 公交换乘 · 方案二 时间窗口优化
- 2020 直播获奖 · 方案一 每轮排序
- 2020 直播获奖 · 方案二 桶计数
- 2021 插入排序 · 方案一 每次真排一遍
- 2021 插入排序 · 方案二 增量维护有序表
- 2022 解密 · 方案一 二分求整数平方根
- 2022 解密 · 方案二 先估后校开方
- 2023 公路 · 方案一 朴素贪心
- 2023 公路 · 方案二 单调栈预处理
- 2024 地图探险 · 方案一 四方向分支写
- 2024 地图探险 · 方案二 方向数组
- 2025 座位 · 方案一 把座位表填出来
- 2025 座位 · 方案二 直接算排名
- 2019 纪念品 · 方案一 逐天完全背包
- 2019 纪念品 · 方案二 砍掉不赚钱物品
- 2020 表达式 · 方案一 每次重算后缀式
- 2020 表达式 · 方案二 建树加关键性传播
- 2021 网络连接 · 方案一 手写解析
- 2021 网络连接 · 方案二 读入后回拼校验
- 2022 逻辑表达式 · 方案二 递归下降
- 2023 一元二次方程 · 方案一 照公式逐步写
- 2023 一元二次方程 · 方案二 拆成小函数
- 2024 小木棍 · 方案一 先定位数再贪心
- 2024 小木棍 · 方案二 预处理最小数字表
- 2025 异或和 · 方案一 贪心能接就接
- 2025 异或和 · 方案二 动态规划加值域数组
- 2019 加工零件 · 方案一 递归加记忆化
- 2019 加工零件 · 方案二 奇偶最短路
- 2020 方格取数 · 方案一 深搜回溯
- 2020 方格取数 · 方案二 按列动态规划
- 2021 小熊的果篮 · 方案一 每轮扫一遍
- 2021 小熊的果篮 · 方案二 链表加有序集合
- 2022 上升点列 · 方案一 先只考虑不加点
- 2022 上升点列 · 方案二 二维动态规划
- 2023 旅游巴士 · 方案一 分层图加优先队列
- 2023 旅游巴士 · 方案二 状态压成一维
- 2024 接龙 · 方案一 按定义广搜
- 2024 接龙 · 方案二 滑动窗口逐轮推进
- 2025 多边形 · 方案一 枚举所有子集
- 2025 多边形 · 方案二 排序加计数 DP