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

P7073 [CSP-J2020] 表达式

时间:2023-10-02 09:22:46浏览次数:42  
标签:int mid 每次 bool P7073 ans CSP 表达式 J2020

Problem

考察算法:后缀表达式建树,优化。

题目简述

读入一个后缀表达式,由 \(\&,\mid,!\) 三种运算和操作数构成。

有 \(q\) 次询问,每次输入一个下标 \(i\) ,表示要取反 \(x_i\) 的值。每次求表达式的值。

暴力

每次重新建表达式树,计算。

时间复杂度:\(O(q \times |s|)\),达到了惊人的 \(10^{11}\)。

优化点

从上向下深搜,记录哪些点的值变化会导致结果的变化

思路

  • 建立表达式树,并求出表达式的值,记录在变量 \(ans\) 中。
  • 用一个 \(bool\) 数组记录那些点的值会导致结果的变化。例如运算符是 \(\mid\) ,如果 \(\mid\) 的左孩子为 \(1\),那么他的右孩子无论是 \(0/1\) ,都不会影响表达式的值为 \(1\) 。
  • 每次询问判断是否会修改当前表达式的值,如果会,输出 \(!ans\),否则输出 \(ans\)。

代码

#include <bits/stdc++.h>

using namespace std;

const int N = 1e6 + 10;
struct node{
	int to, next;
} a[N];
int pre[N], k, num[N], m, n;
char c[N];
bool f[N];
string s, w;
stack<int> st;


void dfs(int x) {
	f[x] = true;
	if (x <= n) return;
	if (c[x] == '!') dfs(a[pre[x]].to);
	else {
		int n1 = a[pre[x]].to, n2 = a[a[pre[x]].next].to;
		if (c[x] == '&') {
			if (num[n1]) dfs(n2);
			if (num[n2]) dfs(n1);
		} else if (c[x] == '|') {
			if (!num[n1]) dfs(n2);
			if (!num[n2]) dfs(n1);
		}
	}
}

void add(int x, int y) {
	a[++k] = {y, pre[x]};
	pre[x] = k;
}

int main() {
	getline(cin, s);
	scanf("%d", &n);
	for (int i = 1; i <= n; i++) {
		scanf("%d", &num[i]);
	}
	int x, y;
	m = n;
	for (int i = 0; i < s.size(); i++) {
		if (isdigit(s[i])) {
			w += s[i];
			if (i == s.size() - 1 || !isdigit(s[i + 1])) {
				st.push(stoi(w));
				w = "";
			}
		} else if (s[i] == '!') {
			m++;
			c[m] = s[i];
			x = st.top();
			st.pop();
			add(m, x);
			num[m] = !num[x];
			st.push(m);
		} else if (s[i] == '&' || s[i] == '|') {
			m++;
			c[m] = s[i];
			x = st.top();
			st.pop();
			y = st.top();
			st.pop();
			add(m, x), add(m, y);
			if (s[i] == '&') num[m] = num[x] & num[y];
			else if (s[i] == '|') num[m] = num[x] | num[y];
			st.push(m);
		}
	}
	int ans = num[st.top()];
	dfs(st.top());
	int q;
	scanf("%d", &q);
	while (q--) {
		scanf("%d", &x);
		if (f[x]) printf("%d\n", !ans);
		else printf("%d\n", ans);
	}
	return 0;
}

标签:int,mid,每次,bool,P7073,ans,CSP,表达式,J2020
From: https://www.cnblogs.com/yhx0322/p/17739714.html

相关文章

  • P7072 [CSP-J2020] 直播获奖
    Problem考查知识点:桶优化。题目简述竞赛的获奖率为\(w\%\),即当前排名前\(w\%\)的选手的最低成绩就是即时的分数线。若当前已评出了\(p\)个选手的成绩,则当前计划获奖人数为\(\max(1,\lfloorp\timesw\%\rfloor)\),如有选手成绩相同,则所有成绩并列的选手都能获奖,因此实......
  • P7074 [CSP-J2020] 方格取数
    Problem相关算法:\(DP\)。题意简述给你一个方格图,每次只能向上、向右、向下走。现在求:经过所有点取到的数字和的最大值。思路动态规划。对于每一列而言,如果某个点向上走了,就不可能再向下走。向下走了同理。所以我们可以把两种情况都尝试一遍,每个点而言,如果是处于向下的状态......
  • CSP模拟30
    CSP模拟30难得改完一次题,写篇题解祭一下A.枫(P7485「Stoi2031」枫)考场居然打了个高分暴力我的思路:假设我们已知最后一个数,逆推,不断往该数前(或后)加了多少数,直至完成这个操作。荣获$96pts$的好成绩评测记录代码如下:#include<bits/stdc++.h>usingnamespacestd;constin......
  • CSP2023 游记
    前言:之所以不在标题中加上&这个字符以及后面那几个字,是准备在复赛后加。今年没报J。下文的qbn,yh,lyl,yts。正文:初赛:每次敲code都用g++编译,甚至暑假在jcsy的时候由于配置VC较麻烦,直接手敲命令的,结果选择题第11题还对不了。。。阅读程序最后一题连错两道......
  • CSP-S 2021 廊桥分配 题解
    part1:题目描述:当一架飞机抵达机场时,可以停靠在航站楼旁的廊桥,也可以停靠在位于机场边缘的远机位。乘客一般更期待停靠在廊桥,因为这样省去了坐摆渡车前往航站楼的周折。然而,因为廊桥的数量有限,所以这样的愿望不总是能实现。机场分为国内区和国际区,国内航班飞机只能停靠在国内......
  • 2023 CSP-S 备战
    2023CSP-S备战日常犯智9.29Dinic中,如果rest为\(0\),直接终止循环。intdinic(intu,intflow){ if(u==T)returnflow; intrest=flow; for(inti=now[u];i&&rest;i=edge[i].nxt){//rest now[u]=i; intv=edge[i].v,c=edge[i].c; ......
  • 洛谷 P7075[CSP-S2020] 儒略日
    [CSP-S2020]儒略日题目描述为了简便计算,天文学家们使用儒略日(Julianday)来表达时间。所谓儒略日,其定义为从公元前4713年1月1日正午12点到此后某一时刻间所经过的天数,不满一天者用小数表达。若利用这一天文学历法,则每一个时刻都将被均匀的映射到数轴上,从而得以很方便的......
  • 济南 CSP-S NOIP 储备营笔记
    Day1上午——基础算法模拟+枚举小前言碰到题目不会做->先写个模拟压压惊()枚举法枚举的思想是不断地猜测,从所有可能的集合中一一尝试,然后再判断是否符合题目的条件。单独提到枚举时我们往往认为这是一个暴力做法,但事实上并非如此,恰当的枚举往往会是解题的关键步骤。......
  • 洛谷 P7075 [CSP-S2020] 儒略日
    P7075[CSP-S2020]儒略日1.题目描述为了简便计算,天文学家们使用儒略日(Julianday)来表达时间。所谓儒略日,其定义为从公元前4713年1月1日正午12点到此后某一时刻间所经过的天数,不满一天者用小数表达。若利用这一天文学历法,则每一个时刻都将被均匀的映射到数轴上,从而得以......
  • CSP-J/S 2023 游记
    \(9.16\)初赛。\(9:00\)就到了振万教学楼,休息了一下,准备去\(5\)楼考场。\(9:05\)到了考场门口,发现教室里面已经开了空调,但xxs们都不进去,6。于是我第一个进了考场。\(9:30\)总算看到试题卷了,好像除了第\(4,10\)题都很简单。\(10:20\)做完了卷子,开始检查。\(11:30\)......