CSP 2020 第三题:表达式

news2024/9/30 15:35:17

牛客网题目
题目内容
在这里插入图片描述

在这里插入图片描述
示例1
输入

x1 x2 & x3 |
3
1 0 1
3
1
2
3

输出

1
1
0

题意:
给出后续表达式,需要计算这个表达式的值,并让某几个变量值取反,再输出新的表达式的值(变量改变均为临时的)
知识点考察:
后缀表达式-栈、树(结构体)、递归
思路:

  • 首先要计算表达式,后缀表达式:左右根,数据放在栈里面,当遇到运算符(根)就弹出并计算值,然后接着入栈、出栈计算即可。如果表达式和数值不变,压栈和出栈的过程就能计算出结果。
  • 但是本题需要更改变量值,所以后缀表达式的数据关系还需要放在树里面,方便后面的查询或者操作。因此建立一个结构体数组,每个结构体储存左孩子和右孩子,储存变量序号,再设置一维数组,序号做下标,储存变量的值和符号的值(直接设为2或者3就行)。当遇到运算符时,保存压在栈中数据分别储存为右节点和左节点,根节点就储存运算符,运算符为了方便储存为数字,可以直接约定一个数字储存,为了避免和前面的孩子节点序号的冲突,直接将约定数据设置得比变量序号最大值大就行,即结构体的根节点序号是从MAX_N+1开始。
  • 按照理由,当变量值变化时,直接再次计算:利用递归,从根节点开始搜索,找到左右孩子然后返回计算的即通过(注意每次改变都是临时改变,)。but ,保守来看:数据长度 105 * 改变次数 106=1011,会超时。由于数据都是0 1,结合”& | “的性质可以想到,”& “的一个孩子结点为0,则当前计算为0(另一个节点为无效节点);同理” | “中一个节点为1,则结果为1(另一个节点为无效节点)。因此只要是如果改变的是有效节点,结果直接取反就行(结果都是0 1)。所以可以设置一个数组mark[],记录该节点是否是无效节点,如果是,直接输出之前的结果,否则直接取反。这个想清楚了可以拿到至少30%的分。
    在这里插入图片描述
  • 接下来时处理取反操作,取反可以想到两个,一个是变量取反,一个是表达式结果取反——(!a&b ) = !a | !b。表达式取反如果挨个用if去处理,也可以直接用异或运算即直接将根节点和1异或处理、同时左右节点分别和1异或处理

异或逻辑的关系是:当AB不同时,输出1;当AB相同时,输出0。"⊕"是异或运算符号,计算机中“^”是异或数学运算符号,满足交换律和结合律
2^1 = 3 , 3^1=2 ,1 ^1=0 ,0^1
在这里插入图片描述

数据约束:

  • s长度最大为 1106 所以长度最大为100000 ,但是实际储存数据时,运算符是以变量序号后面的数来存,必须大一点,>=10000002
  • 结构体数组的长度也是,结构体下标是以运算符的数字来储存,也必须保证开到100000*2,否则会有溢出,出现问题
    参考代码:
#include<bits/stdc++.h>
#include<stack>
#define MAX_N 1000005
using namespace std;
stack <int> st;//定义数据类型char的栈处理后缀表达式 
struct Node{
	int left;
	int right;
}tr[MAX_N*2];//节点树 
int a[MAX_N*2],m[MAX_N*2],f[MAX_N*2]; //存变量值和标记是否有影响的点以及是否是需要取反的点 
 //通过从根节点开始 递归计算出左右子树的值 
 int val(int k); 
 //如果已经被标记 直接标记其孩子 
 void mark(int k);
int main(){
	int yc=MAX_N+1; //给运算符的地址编号 
	int n=0, q,ans=0; //存变量个数、需要改变的数据个数 、存储结果 
    string  s0;//由于变量是x+数字 所以需要根据空格来分隔 判断出每个数据 
    cin>>s0;//如果一次获取一排就要单独处理 
	while(s0[0]>='9'||s0[0]<='0'){    //只要不是数组开头说明还是在输入表达式 
		int k=0; //获取变量的数字 
		int len = s0.size() ;
		if(s0[0]=='x'){ //变量需要转化成数字处理一下(数位合并) 
			for(int i=1;i<len;i++){
				k=k*10+s0[i]-'0';
			} 
			st.push(k); //把当前变量的名放到栈里面 
		}else if(s0[0]=='&'){
			//取出操作数 放到数里面找到左右孩子
 			int rt = st.top() ; 
			st.pop();
			int lt = st.top();
			st.pop();
			st.push(yc) ;//将运算符地址压入栈 
			tr[yc].left = lt; //出栈处理后放到数据树里面,记录当前运算符的左孩子和右孩子 
			tr[yc].right = rt;
			a[yc] = 2 ;//记录当前运算符的值,随便赋即可,a前面都是变量的数据 
			yc++;//后面的运算符将往后算 			
		}else if(s0[0]=='|'){
					int rt = st.top() ; st.pop();
					int lt = st.top(); st.pop();
					st.push(yc) ;
					tr[yc].left = lt; 
					tr[yc].right = rt;
					a[yc] = 3 ;
					yc++;
		}else if(s0[0]=='!'){
				//对前面的得到的这个数取反
				f[st.top()]=!f[st.top()];
				
		} 
			cin>>s0; //继续输入表达式 
	}
		//以上的得到一个string需要转化成数字
		for(int i=0;i<s0.size();i++){
			n=n*10+s0[i]-'0';
		} 
		for(int i=1;i<=n;i++){ //从1开始 因为 变量是从1开始的 
			cin>>a[i] ;
		} 
		yc--;
		ans = val(yc);// 计算结果
		mark(yc);
		cin>>q;
		int l;
//		cout<<"--------更换后-------"; 
		for (int i=1;i<=q;i++){
			cin>>l;
			if(m[l]) cout<<ans<<endl; //结果不受影响(无效点) 
			else {
			  cout<<!ans<<endl; 
			}
		} 
		return 0;
	}
int val(int k){ 
 	//如果是0 1取反结果就是异或结果,如果 2 3取反 则刚好为3 2和运算取反的结果刚好也一致,同时左右孩子也取反就行 
 	//但是!一次递归只需要处理一个值,所以左右孩子异或取反数组就行,不能直接把左右孩子都处理了 
 	a[k] ^= f[k];
 	f[tr[k].left] ^= f[k]; 
	f[tr[k].right] ^= f[k];

    int p=0;
 	if(k<=MAX_N) {
        p=a[k];
        return p;
        
    } //普通节点 
 	int lt = val(tr[k].left);
 	int rt = val(tr[k].right);
 	if(a[k]==2){ //&运算一边为0都为0 
 		if(lt == 0 ) m[tr[k].right]=1;
 		if(rt == 0) m[tr[k].left]=1;
        p=lt&rt;
	}
	else if(a[k]==3){ //|运算一边1都为1 
 		if(lt == 1 ) m[tr[k].right]=1;
 		if(rt == 1) m[tr[k].left]=1;
        p=lt|rt;
// 	cout<<"a[k] 3: "<< "左:"<<a[lt]endl;
	 }
	return p;
 }
void mark(int k){
	if(k>MAX_N)  {
	 	if(m[k]){
	 		m[tr[k].left] = 1;
	 		m[tr[k].right] = 1;
		 }
		if((k-1)>MAX_N) mark(--k);//直接访问下一个符号节点 
	 }
 } 


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1979948.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于Orangepi全志H616学习Python3

目录 一、功能需求 二、Python的安装和环境搭建 三、Python的基础学习 3.1 Python的特点&#xff1a; 3.2 编写并运行第一个Python程序&#xff1a; 3.3 标识符&#xff1a; 3.4 关键字&#xff1a; 3.5 注释&#xff1a; 3.6 行与缩进&#xff1a; 3.7 多行语句&…

虚拟机(CentOS7)安装jenkins

centos7安装jenkins 前提条件&#xff0c;安装jdk与maven 1、JDK17安装 # 进入系统管理员 sudo root # 进入对应文件夹下 cd /usr/local # 下载jdk17 wget https://download.oracle.com/java/17/latest/jdk-17_linux-x64_bin.rpm # rpm命令安装下载的jdk17 rpm -ivh jdk-17_li…

从根儿上学习spring 七 之run方法启动第四段(1)

图1 一步一步我们转眼间来到了第四部分&#xff0c;这是spring最核心的部分包含了bean的整个生命周期过程&#xff0c;不过大家不用担心如果内容过长我会分多个小节来说明以防止一篇文章让大家看晕看累难以吸收理解。让我们直接进入正题。 我们先进入图1的refreshContext方法看…

PEX实验

一、kickstart自动安装脚本制作 1.关闭本机dhcp服务 2.安装图形化生成kickstart自动安装脚本的工具 3.配置http服务 下载httpd 启动并挂载 3.启动图形制作工具 system-config-kickstart 4.配置ks.cfg 5.拷贝到/var/www/html/中去 6.浏览器测试 配置dhcp服务 测试 二.搭建pex…

【JVM基础11】——垃圾回收-说一下JVM的分代回收?

目录 1- 引言&#xff1a;分代回收1-1 什么是分代回收&#xff08;What&#xff09;1-2 为什么要用分代回收&#xff1f;&#xff08;Why&#xff09; 2- ⭐核心&#xff1a;分代回收工作机制2-1 工作机制2-2 MinorGC、Mixed GC、FullGC的区别是什么 3- 总结3-1 说一下 JVM 的分…

【Java 第三篇章】注释、数据类型、运算符

一、注释 Java 中的注释有三种方式&#xff1a;单行注释、多行注释、文档注释。 1、单行注释语法 // 这是单行注释2、多行注释 /** 这是多行注释*/3、文档注释 /*** 这是文档注释*/二、数据类型 Java 中有 8 中基本数据类型&#xff0c;分别为&#xff1a;整型&#xff08;b…

数据结构实验报告-排序

桂 林 理 工 大 学 实 验 报 告 一、实验名称 实验8 排序 二、实验内容&#xff1a; 分别采用直接插人排序、希尔排序、冒泡排序、快速排序、简单选择排序、堆排序、归并排序等排序算法对简单的整型数组进行排序,并输出排序结果。 源码&#xff1a;#include <iostre…

分享一个简单线性dp

我们可以o(n^2)&#xff0c;枚举每一个布告&#xff0c;然后从后往前枚举i前面的位置&#xff0c;然后状态转移 void solve() {int n;cin >> n;vector<int> a(n 1);for (int i 1; i < n; i) cin >> a[i];vector<int> f(n 1, 0x3f3f3f3f);f[0] …

【分隔链表】python刷题记录

R3-双指针&#xff08;快慢指针&#xff09; 新建两个链表 一个链表记录<x的值 一个链表记录>x的值 拼接即可 # Definition for singly-linked list. # class ListNode: # def __init__(self, val0, nextNone): # self.val val # self.next ne…

C语言 | Leetcode C语言题解之第322题零钱兑换

题目&#xff1a; 题解&#xff1a; int coinChange(int* coins, int coinsSize, int amount) {int dp[coinsSize1][amount1];for(int i0;i<coinsSize;i){for(int j0;j<amount;j){dp[i][j]INT_MAX-1;//初始化值为INT_MAX-1&#xff0c;避免后续加一导致溢出}}for(int i0;…

Python | Leetcode Python题解之第321题拼接最大数

题目&#xff1a; 题解&#xff1a; class Solution:def maxNumber(self, nums1: List[int], nums2: List[int], k: int) -> List[int]:m, n len(nums1), len(nums2)maxSubsequence [0] * kstart, end max(0, k - n), min(k, m)for i in range(start, end 1):subsequen…

语言无界,沟通无限:2024年好用在线翻译工具推荐

随着技术的发展现在的翻译在线工具从基础词句翻译到复杂的文章翻译都不在话下。为了防止你被五花八门的工具挑花眼&#xff0c;我给你介绍几款我用过的便捷、高效、准确的翻译工具吧。 1.福晰翻译端 链接直通&#xff1a;https://www.foxitsoftware.cn/fanyi/ 这个软件支持…

Google上架:8月份政策改动,未在8月31日前回应做出改动的包体将会有下架的风险

谷歌一直以用户为中心的服务思想,政策一直在变动,未及时变动的包体又下架甚至封号的风险,如有以下情况,请及时检查包体或账号相关问题,希望能给各位开发者带来帮助。 截止提交时间 2024-08-31 支付相关要求变动公布日期改动须知更改要求垃圾应用包体与用户体验公布日期改动…

LinuxC++(9):进程

linux信号 linux信号单指给进程发送的信息。比如killall 就是杀死进程&#xff0c;其实这个描述并不准确&#xff0c;应该是给程序发送一个信号&#xff0c;让程序自我了断&#xff0c;并不是我们亲自动手。 为什么直接杀死进程不好&#xff1f; 因为直接杀死进程&#xff0…

JAVA毕业设计|ssm基于ssm的宠物医院管理系统的设计与实现vue包含文档代码讲解

收藏点赞不迷路 关注作者有好处 文末获取源码 一、系统展示 二、万字文档展示 基于ssm基于ssm的宠物医院管理系统的设计与实现vue 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringSpringMVCMyBatisVue 工具&#xff1a;IDEA/Ecilpse、Navicat、Ma…

SQL注入实例(sqli-labs/less-5)

0、初始页面 1、确定闭合字符 ?id1 and 11 ?id1 and 12 ?id1 ?id1 -- 在进行前两句传参时&#xff0c;页面没有发生任何变化&#xff0c;但是当使用单引号闭合时&#xff0c;报错了。通过报错可以确定闭合符号为单引号。 2、爆库名 ?id1 and updatexml(1,concat(0x7e,(…

腾讯HunyuanDit代码解析

注意&#xff1a;本文仅供自己记录学习过程使用。 训练 全参训练过程 输入图像用VAE编码得到输入的x_start(1,4,128,128)&#xff1b;文本的两个特征&#xff1a;bert的encoder feature(1,77,1024)和T5 的feature(1,256,2048)&#xff0c;和旋转位置编码freqs_cis_img: cos …

4.8.双向循环神经网络

双向循环神经网络 ​ 在序列模型中&#xff0c;我们总是关注之前的信息&#xff0c;并以此来对下一个输出进行预测&#xff0c;但可能未来的信息也很重要&#xff0c;比如文本序列填空&#xff1a; 我___。我___饿了。我___饿了&#xff0c;我可以吃半头猪。 ​ 我们可以分别…

数据安全复合治理与实践

数据安全复合治理与实践 关键要点理论与实践 本文探讨了数据安全复合治理模式的理论与实践&#xff0c;着重强调了在数字经济迅猛发展的背景下&#xff0c;数据安全的重要性以及面对数据安全挑战时所需采取的综合治理策略。首先&#xff0c;文章概述了数据安全治理的必要性&…

使用GPT-4o mini融合GraphRAG技术进行实战应用

什么是gpt-4o mini OpenAI 推出 GPT-4o mini&#xff0c;这是他们最具成本效益的小型模型。它的定价为每百万输入代币 15 美分&#xff0c;每百万输出代币 60 美分&#xff0c;比之前的 Frontier 型号便宜一个数量级&#xff0c;比 GPT-3.5 Turbo 便宜 60% 以上。目前&#xf…