首页 > 其他分享 >【题解】洛谷#P7073 [CSP-J2020] 表达式

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

时间:2023-10-06 19:22:06浏览次数:52  
标签:操作数 洛谷 val int 题解 st fa P7073 表达式

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

Description

给定一个逻辑表达式和其中每一个操作数的初始取值后,再取反某一个操作数的值时,求出原表达式的值。表达式将采用后缀表达式的方式输入。

Solution

根据题目可得,当取反一个操作数的值时,整个表达式大体只有变与不变两种情况,而往下分解,整个表达式可以被分成若干子表达式,然后子表达式继续分解······

这样,我们就可以把表达式直接当作一棵树,而操作数\(x\)取反是否会改变表达数的值,或者说它是否起到决定性的作用取决于它所在的子表达式,而子表达式又有可能影响到更上一级的表达式······最后是到整个表达式,

我们发现,如此将一个操作数逐层递增,最后爬到根节点的操作可以用类似并查集的方法实现,如果这层递增后发现起到决定性的作用时,继续递增,当最后递增到整个表达式的范畴时,则输出原表达式结果的取反结果,否则直接输出结果

Step

  1. 读入表达式和操作数初值

  2. 计算表达式,同时判断每个操作数是否起到决定性的作用,分或运算\(|\)和与运算\(\&\)两种情况:

  • 当是或运算且另一个操作数为0时,这个操作数就将起着决定性的作用

  • 当是与运算且另一个操作数为1时,这个操作数就将起着决定性的作用

  1. 输入查询,判断是否影响到整个表达式,如是则输出结果的取反结果,否则直接输出结果

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

标签:操作数,洛谷,val,int,题解,st,fa,P7073,表达式
From: https://www.cnblogs.com/FrankC/p/17744864.html

相关文章

  • CF1010C Border 题解
    题目传送门前置知识最大公约数|裴蜀定理简化题意给定一个长度为\(n\)的序列\(a\),求能用\(r=(\sum\limits_{i=1}^{n}d_ia_i)\bmodk\)表示的不同的\(r\)的个数及所有情况,其中对于每一个\(i(1\lei\len)\)均有\(d_i\)为非负整数。解法依据裴蜀定理,不难得到存......
  • CF131D Subway 题解
    题目传送门前置知识强连通分量|最短路解法考虑用Tarjan进行缩点,然后跑最短路。缩点:本题的缩点有些特殊,基于有向图缩点修改而得,因为是无向图,所以在Tarjan过程中要额外记录一下从何处转移过来,防止在同一处一直循环。基环树上找环还有其他方法,这里仅讲解使用Tarjan求......
  • 题解: P6933
    题目传送门这道题我用的是二分答案,只不过这道题和一般的二分答案有些不同,是浮点数的二分答案。那自然和整数的二分答案有些不同,下面我会说到。我们先来看一下思路解法。思路解法首先确定了是二分答案,我们需要先确定初始的\(l\)和\(r\)和check函数。check函数好写,我们......
  • 【UVA 514】Rails 题解(栈+队列)
    PopPush市有一个著名的火车站。那个里的乡村是令人难以置信的丘陵。车站建于上世纪。不幸的是,当时资金极其有限。有可能仅建立表面轨迹。此外,事实证明,该站可能只是一个死胡同(见图片),由于缺乏可用空间,它只能有一个轨道。当地的传统是,每一列从A方向到达的火车都会继续朝A方向行驶......
  • 【题解 P4550】 收集邮票
    收集邮票题目描述有\(n\)种不同的邮票,皮皮想收集所有种类的邮票。唯一的收集方法是到同学凡凡那里购买,每次只能买一张,并且买到的邮票究竟是\(n\)种邮票中的哪一种是等概率的,概率均为\(1/n\)。但是由于凡凡也很喜欢邮票,所以皮皮购买第\(k\)次邮票需要支付\(k\)元钱。现......
  • neovim的插件管理器vim-plug导致代码颜色不显示问题解决
    neovim的帮助文件路径F:\Programs\Neovim\share\nvim\runtime\docruntimepath的帮助文档路径F:\Programs\Neovim\share\nvim\runtime\doc\options.txt$VIM环境变量$VIM被用来确定Vim中不同的用户文件的位置,比如用户启动脚本“.vimrc”。这个是系统设置,详见startup。允许每......
  • 关于洛谷题解审核
    我想问一下,大家觉得题解的重点是什么?很显然是思路,代码的正确性,次要的才是格式。但是,洛谷对于题解格式的审核是不是有点过于严格了呢?比如说这段话:如果\(n\)为\(0\),那么便是无解。大家能一眼看出,后面多了空格吗?这种题解其实没什么大问题,别人看题解时根本不会在意这些......
  • 【bitset】【线段树】CF633G Yash And Trees 题解
    CF633G简单题。先看到子树加和子树质数个数和,果断转换为dfs序进行处理。既然有区间求和,考虑线段树。若对于每一个节点维护一个\(cnt\)数组,用二进制数\(x\)来表示,即当\(cnt_i=1\)时第\(i\)位为\(1\)。设当前节点为\(u\),左右子节点分别为\(ls\)和\(rs\)。发现......
  • 洛谷 P7830 [CCO2021] Through Another Maze Darkly
    洛谷传送门被联考创出shit了。考虑一种极限情况:每个点指向父亲。那么这种情况我们会顺着欧拉序完整地把整棵树都走一遍。但是初始的时候不一定每个点都指向父亲。发现我们走过\(O(n^2)\)步就能到达上面的极限情况。比较显然,因为每次扩展至少使一个点从不指向父亲变成指向父......
  • 【倍增】P3422 [POI2005]LOT-A Journey to Mars 题解
    P3422一道有点意思的题。看到是一个环,先破环为链,即\(a_{n+i}=a_i,b_{n+i}=b_i\),此时就只需要跳到\(x+n\)而无需判环了。如果顺时针走:令\(sum_i=\sum\limits_{j=1}^{i}{a_j-b_j}\),当能从\(x\)跳到\(x+n\)时,有\[sum_{x-1}\lesum_x,sum_{x-1}\lesum_{x+1},\dot......