CSP-J 2020 T3 表达式
我们来看题面:
1.给后缀表达式
2.多次询问,应该需要打表
**************************************************************************************************************
后缀表达式:
1.栈(会超时)
2.建表达式树(二叉树通常拿来优化)
**************************************************************************************************************
有了二叉树,我们就会想到DFS
那具体如何DFS呢?
我们可以这样:
1.用DFS求原表达式
2.新建DFS函数来看这里的点改变后,是否会影响表达式的值
*************************************************************************************************************
所以便有了整体思路:
1.建表达式树
2.DFS记表
3.读入询问,看是否会改变
**************************************************************************************************************
整体代码:
#include <bits/stdc++.h>
using namespace std;
#define N 400005
string str;
int n, q, cnt;
vector<int> tree[N];
char o[N];
int v[N];
stack<int> stk;
bool flag[N];
int dfs1(int root)
{
if(root <= n) return v[root];
if(o[root] == '&') return v[root] = dfs1(tree[root][0]) & dfs1(tree[root][1]);
if(o[root] == '|') return v[root] = dfs1(tree[root][0]) | dfs1(tree[root][1]);
if(o[root] == '!') return v[root] = !dfs1(tree[root][0]);
}
void dfs2(int root)
{
flag[root] = true;
if(o[root] == '&')
{
if(v[tree[root][0]] == 1) dfs2(tree[root][1]);
if(v[tree[root][1]] == 1) dfs2(tree[root][0]);
}
if(o[root] == '|')
{
if(v[tree[root][0]] == 0) dfs2(tree[root][1]);
if(v[tree[root][1]] == 0) dfs2(tree[root][0]);
}
if(o[root] == '!') dfs2(tree[root][0]);
}
int main()
{
getline(cin, str);
cin >> n;
for(int i = 1; i <= n; i++) cin >> v[i];
cnt = n + 5;
for(int i = 0; i < str.length(); i++)
{
if(str[i] == 'x')
{
int num = 0;
int j = i + 1;
while(str[j] >= '0' && str[j] <= '9')
{
num = num * 10 + str[j] - '0';
j++;
}
stk.push(num);
}
else if(str[i] == '&' || str[i] == '|')
{
int a = stk.top(); stk.pop();
int b = stk.top(); stk.pop();
stk.push(++cnt);
tree[cnt].push_back(a);
tree[cnt].push_back(b);
o[cnt] = str[i];
}
else if(str[i] == '!')
{
int a = stk.top(); stk.pop();
stk.push(++cnt);
tree[cnt].push_back(a);
o[cnt] = '!';
}
}
int res = dfs1(stk.top());
dfs2(stk.top());
int t;
cin >> q;
for(int i = 1; i <= q; i++)
{
cin >> t;
if(flag[t]) cout << !res << endl;
else cout << res << endl;
}
return 0;
}
CSP-J2022 T3 逻辑表达式:
和上一道题有异曲同工之处:
1.都是表达式
2.都需用DFS优化
不同的是给了中缀表达式
那么我们也可以得到本题思路:
1.建表达式树
2.DFS求值+计算短路次数
即可得到答案
代码:
#include <bits/stdc++.h>
using namespace std;
string s;
vector <int> vec[2000005];
char o[2000005];
int ans1, ans2, res;
int n, cnt;
int val[2000005];
string sf;
stack<int> ops;
void change()
{
for(int i=0;i<s.size();i++)
{
if(s[i]=='0'||s[i]=='1')sf += s[i];
else if(s[i]=='(')ops.push(s[i]);
else if(s[i]==')')
{
while(!ops.empty()&&ops.top()!='(')
{
sf += ops.top();
ops.pop();
}
ops.pop();
}
else if(s[i] == '&')
{
while(!ops.empty()&&ops.top()=='&')
{
sf += ops.top();
ops.pop();
}
ops.push('&');
}
else
{
while(!ops.empty()&&ops.top() != '(')
{
sf += ops.top();
ops.pop();
}
ops.push('|');
}
}
while(!ops.empty())
{
sf += ops.top();
ops.pop();
}
}
void buildtree()
{
change();
//cout << sf << endl;
stack<int> stk;
for(int i = 0; i < sf.size(); i++)
{
if(sf[i] == '0' || sf[i] == '1')
{
val[++n] = sf[i] - '0';
stk.push(n);
}
else if(sf[i] == '&' || sf[i] == '|')
{
int a = stk.top(); stk.pop();
int b = stk.top(); stk.pop();
stk.push(++cnt);
vec[cnt].push_back(b);
vec[cnt].push_back(a);
o[cnt] = sf[i];
}
}
}
int dfs1(int root)
{
if(root <= n) return val[root];
if(o[root] == '|') return val[root] = dfs1(vec[root][0]) | dfs1(vec[root][1]);
if(o[root] == '&') return val[root] = dfs1(vec[root][0]) & dfs1(vec[root][1]);
return 0;
}
void dfs2(int root)
{
if(o[root] == '&')
{
if(val[vec[root][0]] == 0)
ans1++;
else dfs2(vec[root][1]);
dfs2(vec[root][0]);
}
if(o[root] == '|')
{
if(val[vec[root][0]] == 1)
ans2++;
else dfs2(vec[root][1]);
dfs2(vec[root][0]);
}
}
int main()
{
cin >> s;
n = 0;
cnt = s.size() + 5;
buildtree();
dfs1(cnt);
dfs2(cnt);
cout << val[cnt] << "\n" << ans1 << " " << ans2 << endl;
return 0;
}
关注劳大,让你们永远得吃