P7073 表达式(expr)
说在前面
考场上的我是真的逊,expr
代码都写出来了结果没有更新到D:/submit
而爆零。
题意简述
给你一个后缀表达式,只有&
,|
,!
运算,有个变量,为,其中任意,给的初值,个操作,每次操作:
给一个整数,要求将的值取反,求这个表达式的值。
数据范围:
- 运算仅有
&
和|
- 另外
- 另外,变量初值全部相同。
简单口胡
- 每次进行表达式运算,,逊
部分分只会这一个
正解:考虑对取反是否会影响整个式子的值,先建一个表达式树,对于每个节点,它和它的子树也是一个表达式,其中对于非叶节点,这个节点是一个运算符,这个表达式的值为, 为这个运算符,和为这个节点的左子树表达式的值和右子树表达式的值。
分类讨论:
- 如果这个节点是叶子,啥事没有
- 如果这个节点是
&
,那么:
如果,那么这个表达式的值肯定为,也就是说对答案没有贡献,给右子树里的所有节点打上标记。
同理。
- 如果这个节点是
|
,那么:
如果,那么这个表达式的值肯定为,也就是说对答案没有贡献,给右子树里的所有节点打上标记。
同理。
于是这题就没了,打好标记和计算一开始表达式的答案,对于每一个询问,如果这个询问有标记,代表对其取反对没有变化,否则输出。
大概是?
# include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 5;
int q[N],tot;
int n,val[N / 10];
int ch[N][2];
bool C[N / 10];
int Opt[N];
stack <int> s;
int Get(string st,int l)
{
int ans = 0;
int len = st.size();
for(int i = l; i < len; i++)
{
ans = ans * 10 + st[i] - '0';
}
return ans;
}
int key(char opt)
{
if(opt == '|') return -1;
if(opt == '&') return -2;
if(opt == '!') return -3;
}
void Input(void)
{
string st;
while(cin >> st)
{
if(isdigit(st[0]))
{
break;
}
else
{
if(st[0] == 'x')
{
int num = Get(st,1);
// printf("num = %d\n",num);
q[++tot] = num;
}
else
{
q[++tot] = key(st[0]);
}
}
}
n = Get(st,0);
// printf("n = %d\n",n);
for(int i = 1; i <= n; i++)
{
scanf("%d",&val[i]);
}
return;
}
int dfs(int root)
{
if(root <= n) return val[root];
if(Opt[root] == -3) return !dfs(ch[root][0]);
if(Opt[root] == -1) // or
{
int ans1 = dfs(ch[root][0]),ans2 = dfs(ch[root][1]);
if(ans1 == 1)
C[ch[root][1]] = 1;
if(ans2 == 1)
C[ch[root][0]] = 1;
return ans1 | ans2;
}
else
{
if(Opt[root] == -2) // and
{
int ans1 = dfs(ch[root][0]),ans2 = dfs(ch[root][1]);
if(ans1 == 0)
C[ch[root][1]] = 1;
if(ans2 == 0)
C[ch[root][0]] = 1;
return ans1 & ans2;
}
}
}
void pushup(int root)
{
if(ch[root][0]) C[ch[root][0]] |= C[root];
if(ch[root][1]) C[ch[root][1]] |= C[root];
if(ch[root][0]) pushup(ch[root][0]);
if(ch[root][1]) pushup(ch[root][1]);
return;
}
int main(void)
{
Input();
int cur = n;
for(int i = 1; i <= tot; i++)
{
if(q[i] > 0)
{
s.push(q[i]);
}
else
{
if(q[i] == -3)
{
int a1 = s.top();s.pop();
Opt[++cur] = -3;
ch[cur][0] = a1;
s.push(cur);
continue;
}
int a1 = s.top();s.pop();
int a2 = s.top();s.pop();
Opt[++cur] = q[i];
ch[cur][0] = a1,ch[cur][1] = a2;
s.push(cur);
}
}
// printf("cur = %d\n",cur);
int now = dfs(cur);
pushup(cur);
int test;
scanf("%d",&test);
while(test--)
{
int x;
scanf("%d",&x);
printf("%d\n",C[x] ? now : !now);
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)