首页 > 其他分享 >[CSP-J2020] 表达式 题解

[CSP-J2020] 表达式 题解

时间:2024-10-23 22:20:21浏览次数:1  
标签:运算 lc int 题解 tree solve rc CSP J2020

短路

这道题目中所含的运算符只有3个:与、或、非.

在与运算和或运算中有2个性质.

进行与运算时,若其中有一个值为0,则这个运算的结果就为0,即无需判断

另1个数是否是0或1.

进行或运算时,若其中有一个值为1,则这个运算的结果就为1,也无需判断

另一个数是否是0或1.

表达式树

根据短路的性质,可以得知,在与运算时,如果当前值为1,则需额外判断另

一个数是否为0,1,因为它的值可能会影响整个表达式的值.因此,需要构造一

棵表达式树.

其中,需要存储节点的编号,值,左孩子,右孩子.

染色

在递归的过程中,可以通过染色,判断这个节点对树的值是否有影响.

代码

#include<bits/stdc++.h>
using namespace std;
string s;
int n, x[100005], cnt, num, c[100002], f[1000002];
int q, k;
struct node { // 定义结构体 
	int id, v, lc, rc;
	// 编号,值,左孩子,右孩子 
}t[1000002]; // tree 
stack<int> st;
void post_to_tree() { // 转成表达式树的形式,以链式的方法存储
	// !为-1,|为-2,&为-3 
	for (int i = 0; i < s.size(); i++) {
		if (s[i] == 'x') num = 0; // 如果说当前字符是x,则下一个字符一定是x的下表 
		else if (s[i] >= '0' && s[i] <= '9')
			num = num * 10 + (s[i] - '0'); // 用num存储下来下标的值 
		else if (s[i] == ' ') {
			if (s[i-1] >= '0' && s[i-1] <= '9') { // 上一个是下标 
				t[++cnt] = (node){cnt, num, -1, -1}; // lc, rc = -1, 表示没有 
				st.push(cnt); // 放入栈 
			}
		}
		else if (s[i] == '!') {
			int t1 = st.top();st.pop(); // 拿出栈顶元素
			// 因为!为单目运算符,所以只要存左孩子就行了 
			t[++cnt] = (node){cnt, -1, t1, -1}; // 创建新节点 
			st.push(cnt); // 存编号 
		}
		else if (s[i] == '|') { // | 和 & 为双目运算符,所以要弹2个,并存左孩子和右孩子 
			int t1 = st.top();st.pop();
			int t2 = st.top();st.pop();
			t[++cnt] = (node){cnt, -2, t1, t2};
			st.push(cnt);
		}
		else if (s[i] == '&') {
			int t1 = st.top();st.pop();
			int t2 = st.top();st.pop();
			t[++cnt] = (node){cnt, -3, t1, t2};
			st.push(cnt);
		}
	}
}
bool calc_tree(int u) { // 计算树的原值 
	// 用f数组存值 
	if (t[u].v > 0) // 不是运算符 
		return f[u]=x[t[u].v]; // 在存入f数组中 
	if (t[u].v == -1) // !
		return f[u]=!calc_tree(t[u].lc);
	// 这里千万不能直接或和与,因为根据短路性质,第2个值可能就不算了 
	if (t[u].v == -2) { // |
		bool f1 = calc_tree(t[u].lc);
		bool f2 = calc_tree(t[u].rc);
		return f[u] = f1 || f2; 
	}
	// 这里分开算与或同理 
	if (t[u].v == -3) { // &
		bool f1 = calc_tree(t[u].lc);
		bool f2 = calc_tree(t[u].rc);
		return f[u] = f1 && f2;
	}
}
void solve_tree(int u) {
	if (t[u].v > 0) { // 如果是一个值,那可能会对值造成影响
		c[t[u].v] = 1; // 进行染色 
		return ;
	}
	if (t[u].v == -1) // !运算递归染色 
		solve_tree(t[u].lc);
	if (t[u].v == -2) { // &运算 
		if (f[t[u].lc] == 0) solve_tree(t[u].rc); // 一个为0,则会有短路	
		if (f[t[u].rc] == 0) solve_tree(t[u].lc); // 右边同理 
	}
	if (t[u].v == -3) {
		if (f[t[u].lc] == 1) solve_tree(t[u].rc); // 一个为1,则也会有短路 
		if (f[t[u].rc] == 1) solve_tree(t[u].lc); // 右边同理 
	}
}
int main() {
//	freopen("expr2.in", "r", stdin);
//	freopen("expr2.out", "w", stdout);
	getline(cin, s);
	scanf("%d", &n);
	for (int i = 1; i <= n; i++) scanf("%d", &x[i]);
	// 构建表达式树
	post_to_tree();
	// 计算原值 
	calc_tree(cnt);
	// 递归自己的改变是否影响原值 
	solve_tree(cnt);
	scanf("%d", &q);
	for (int i = 1; i <= q; i++) {
		scanf("%d", &k);
		if (c[k]) printf("%d\n", !f[cnt]); // 被染色,说明会影响原值,取反 
		else printf("%d\n", f[cnt]);
	}
	return 0;
}

标签:运算,lc,int,题解,tree,solve,rc,CSP,J2020
From: https://www.cnblogs.com/panda-lyl/p/18498507

相关文章

  • 题解 SS241023D【数颜色】/ ZROI3029【静态邻域数颜色】
    静态邻域数颜色-题目-ZhengruiOnlineJudge题目描述静态树上邻域数颜色。给一棵\(n\)个点的无根树,第\(i\)个点颜色为\(a_i\)。有\(q\)次询问,每次询问如下:给定\(x,d\),考虑所有距离\(x\)不超过\(d\)的点,求有多少种不同的颜色。形式化地,给定\(x,d\),求\(|\{a......
  • 题解 P5326【[ZJOI2019] 开关】/ SS241023B【判断题】
    已经沦落为可以随便搬进模拟赛的模板题了。。。题目描述当前有\(n\)道判断题,初始全选的错。初始给出每道题的正确答案,设\(0\)表示错,\(1\)表示对。每道题有一个参数\(p_i\),每轮会以\(\frac{p_i}{\sum_{j=1}^{n}p_j}\)的概率选择第\(i\)道题并修改(flip)这道题的答......
  • CSP-J 2024 游记
    CSP-J2024游记Day\(-3\)忐忑不安地期待。做了一套模拟。ProblemScoreDifficultiesA\(100\)入门B\(50\)(贪心策略错了)普及-C\(50\)(双重循环\(n<=10^5\))普及D\(20\)(dp+前缀和,我写的DFS)普及+B题交完废了,幸好后面\(2\)题还行,总分......
  • [COCI2009-2010#4] PALACINKE 题解
    前言题目链接:洛谷。题意简述\(n\)个点,\(m\)条边。每条边上有商店,经过一条边花费\(1\)单位时间,如果在边上的商店购物,额外花费\(1\)单位时间。需要购买\(4\)种物品,每个商店售出\(1\sim4\)种物品不等。请问,在\(T\)个单位时间内,从\(1\)出发购物,得到这\(4\)种物品......
  • CSP模拟赛 #43
    A一棵树,每次加入一条路径,或者查询一条给定路径包含的路径个数。\(n,m,q\le10^5\)矩形加法,单调查询,三维偏序,cdq分治。B一棵树,有\(n+1\)层,第\(i\)层有\(i\)个点。对于第\(i(1\lei\len)\)层,点的编号分别为\(\frac{i(i-1)}2+1\sim\frac{i(i+1)}2\),该层的第......
  • 信息学奥赛复赛复习20-CSP-S2019-01格雷码-数据类型范围、unsigned 关键字、无符号范
    PDF文档回复:202410231P5657[CSP-S2019]格雷码[题目描述]通常,人们习惯将所有n位二进制串按照字典序排列,例如所有2位二进制串按字典序从小到大排列为:00,01,10,11。格雷码(GrayCode)是一种特殊的nn位二进制串排列法,它要求相邻的两个二进制串间恰好有一位不同,特别地......
  • 信息学奥赛复赛复习20-CSP-S2019-01格雷码-数据类型范围、unsigned 关键字、无符号范
    PDF文档公众号回复关键字:202410231P5657[CSP-S2019]格雷码[题目描述]通常,人们习惯将所有n位二进制串按照字典序排列,例如所有2位二进制串按字典序从小到大排列为:00,01,10,11。格雷码(GrayCode)是一种特殊的nn位二进制串排列法,它要求相邻的两个二进制串间恰好有一位不同......
  • [算法题解] Codeforces round 979 --D. QED's Favorite Permutation
    题目链接:https://codeforces.com/contest/2030/problem/D题目:题解:FavotitePermutation即每个数满足i=p[i];此题中,p数组每次询问后保持不变,s根据询问而改变。因此每次需要进行交换的数的位置是相同的,只需要检验s变更后,操作能否满足交换需求与否。故创建需数组need,预处理nee......
  • [CSP-S2020] VP
    【比赛地址】省流:\(100+100+70+55\to100+100+70+0,325\to270\)[CSP-S2020]儒略日乱搞。这道题太恶心了,场上用了\(1h\)才做出来。代码过于抽象,不放了。[CSP-S2020]动物园非常简单的黄题。#include<bits/stdc++.h>usingnamespacestd;unsignedlonglongn,m,c,k......
  • 题解:CF1225E Rock Is Push
    很玄妙的一道dp题。HintAnalysis首先你要确保你会做当石头没有/固定的情况,这道题其实也是dp。考虑石头带来的影响,唯一的作用就是限制你的移动,比方说你下面有\(3\)块石头,由于只能向右或向下移动,你实际上往下只能走到当前列第\(n-3\)行。于是对于石头的处理,设\(rs[i][j......