【题解】洛谷#P7073 [CSP-J2020] 表达式

Description

改变一个逻辑表达式中某个未知数的值,求此时表达式的值

Solution

表达式的值如何变化

几种情况?

在表达式中,改变某个变量的值,表达式只有两种情况:变和不变

这当然不是废话

  • 有些变量对表达式起到决定性作用,其一旦改变,则表达式的值也改变

  • 而有些变量没有任何用处,其是否改变,并不影响表达式的值

而因为是逻辑表达式,所以只有\(0\)\(1\)两种结果,

只需知道是否改变,就能求出表达式最终的值

如何判定?

从简单开始

从最简单的表达式入手,探究变量的值对表达式的值的影响:

\[0 \& x \]

\(x\) 的值决定不了表达式的值,表达式永远为0

\[1 \& x \]

这时,事情开始有趣起来:

  1. \(x=0\) 时,\(1\&x=1\)

  2. \(x=1\)时,\(1\&x=0\)

\(x\)的值对表达式起到决定性作用

  • \[1 | x \]

    \(x\)的值决定不了表达式的值,表达式永远为1

    \[0 | x \]

    1. \(x=0\)时,\(0 | x=0\)

    2. \(x=1\)时,\(0 | x=1\)

    \(x\) 的值对表达式起到决定性作用

  • \[!x \]

    这里读者自己尝试一下,会发现\(x\)的值仍对表达式起到决定性作用

现在,我们已经弄明白在简单表达式中,变量的值如何影响表达式的值

由局部到整体

那读者要问了,题目中的表达式比这个复杂多了,如何处理呢?

让我们换个角度思考问题,

上一板块中的\(x\)一定是一个单纯的变量吗?

如果它是一个子表达式呢?

容易发现,当\(x\)是一个 子表达式时,上述结果仍然成立!

而当某个变量影响到某个子表达式,且该子表达式影响到上一级表达式时,

那么该变量将对整个表达式起决定性作用

如此逐层判断,就能求出表达式最终的值

Code

#include <bits/stdc++.h>
using namespace std;
const int maxE=1e6+5,maxN=1e5+5;
int n,e[maxE],l,wx[maxN],a[maxN],fa[maxE];
struct Node{
    int eid,val;
};
stack<Node>st;
int main(){
    while(1)
    {
        string s;
        cin>>s;
        char c=s[0];
        if(c>='0'&&c<='9')
        {
            n=stoi(s);
            break;
        }
        if(c=='x')
        {
            int xid=stoi(s.substr(1));
            e[++l]=xid;
            wx[xid]=l;
        }
        if(c=='!') e[++l]=-1;
        if(c=='&') e[++l]=-2;
        if(c=='|') e[++l]=-3;
    }
    for(int i=1;i<=n;i++)
        cin>>a[i];
    for(int i=1;i<=l;i++)
    {
        if(e[i]>0)
        {
            st.push({i,a[e[i]]});
        }
        if(e[i]==-1)
        {
            Node x=st.top();st.pop();
            st.push({i,!x.val});
            fa[x.eid]=i;
        }
        if(e[i]==-2)
        {
            Node y=st.top();st.pop();
            Node x=st.top();st.pop();
            st.push({i,x.val&y.val});
            if(x.val==1)fa[y.eid]=i;
            if(y.val==1)fa[x.eid]=i;
        }
        if(e[i]==-3)
        {
            Node y=st.top();st.pop();
            Node x=st.top();st.pop();
            st.push({i,x.val|y.val});
            if(x.val==0)fa[y.eid]=i;
            if(y.val==0)fa[x.eid]=i;
        }
    }
    int res=st.top().val;
    int q;
    cin>>q;
    for(int i=1;i<=q;i++)
    {
        int xid;
        cin>>xid;
        int j=wx[xid];
        while(fa[j])
            j=fa[j];
        if(j==l)
            cout<<!res<<endl;
        else
            cout<<res<<endl;
    }
    return 0;
}

感谢@fyz的代码

好吧,我承认思路也是他的(bushi

posted @ 2023-10-06 19:15  RainDuckling  阅读(170)  评论(0)    收藏  举报