P7073 [CSP-J2020] 表达式

Problem

考察算法:后缀表达式建树,优化。

题目简述

读入一个后缀表达式,由 \(\&,\mid,!\) 三种运算和操作数构成。

\(q\) 次询问,每次输入一个下标 \(i\) ,表示要取反 \(x_i\) 的值。每次求表达式的值。

暴力

每次重新建表达式树,计算。

时间复杂度:\(O(q \times |s|)\),达到了惊人的 \(10^{11}\)

优化点

从上向下深搜,记录哪些点的值变化会导致结果的变化

思路

  • 建立表达式树,并求出表达式的值,记录在变量 \(ans\) 中。
  • 用一个 \(bool\) 数组记录那些点的值会导致结果的变化。例如运算符是 \(\mid\) ,如果 \(\mid\) 的左孩子为 \(1\),那么他的右孩子无论是 \(0/1\) ,都不会影响表达式的值为 \(1\)
  • 每次询问判断是否会修改当前表达式的值,如果会,输出 \(!ans\),否则输出 \(ans\)

代码

#include <bits/stdc++.h>

using namespace std;

const int N = 1e6 + 10;
struct node{
	int to, next;
} a[N];
int pre[N], k, num[N], m, n;
char c[N];
bool f[N];
string s, w;
stack<int> st;


void dfs(int x) {
	f[x] = true;
	if (x <= n) return;
	if (c[x] == '!') dfs(a[pre[x]].to);
	else {
		int n1 = a[pre[x]].to, n2 = a[a[pre[x]].next].to;
		if (c[x] == '&') {
			if (num[n1]) dfs(n2);
			if (num[n2]) dfs(n1);
		} else if (c[x] == '|') {
			if (!num[n1]) dfs(n2);
			if (!num[n2]) dfs(n1);
		}
	}
}

void add(int x, int y) {
	a[++k] = {y, pre[x]};
	pre[x] = k;
}

int main() {
	getline(cin, s);
	scanf("%d", &n);
	for (int i = 1; i <= n; i++) {
		scanf("%d", &num[i]);
	}
	int x, y;
	m = n;
	for (int i = 0; i < s.size(); i++) {
		if (isdigit(s[i])) {
			w += s[i];
			if (i == s.size() - 1 || !isdigit(s[i + 1])) {
				st.push(stoi(w));
				w = "";
			}
		} else if (s[i] == '!') {
			m++;
			c[m] = s[i];
			x = st.top();
			st.pop();
			add(m, x);
			num[m] = !num[x];
			st.push(m);
		} else if (s[i] == '&' || s[i] == '|') {
			m++;
			c[m] = s[i];
			x = st.top();
			st.pop();
			y = st.top();
			st.pop();
			add(m, x), add(m, y);
			if (s[i] == '&') num[m] = num[x] & num[y];
			else if (s[i] == '|') num[m] = num[x] | num[y];
			st.push(m);
		}
	}
	int ans = num[st.top()];
	dfs(st.top());
	int q;
	scanf("%d", &q);
	while (q--) {
		scanf("%d", &x);
		if (f[x]) printf("%d\n", !ans);
		else printf("%d\n", ans);
	}
	return 0;
}
posted @   yhx0322  阅读(177)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示